洛谷 省选营题目 过年

【题解】

  差分+扫描线+权值线段树。

  我们先把区间操作差分,变成2*m个点操作,然后按照位置对操作进行排序。接着按顺序处理每个位置的答案,如果当前位置有操作,就先在权值线段树上修改,再统计当前点的答案。

  要注意的是,题目问的是出现次数最多的礼物的编号,所以权值线段树要维护的不仅是最大值,还有最大值的位置。

#include<cstdio>
#include<algorithm>
#define rg register
#define N 400010
#define ls (u<<1)
#define rs (u<<1|1)
#define mid ((a[u].l+a[u].r)>>1)
using namespace std;
int n,m,pos,cnt[N];
struct tree{
    int l,r,mx;
}a[N];
struct rec{
    int pos,k,type;
}r[N];
inline int read(){
    int k=0,f=1; char c=getchar();
    while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
    while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar();
    return k*f;
}
inline int max(int x,int y){return x>y?x:y;}
inline int cmp(rec a,rec b){return a.pos<b.pos;}
void build(int u,int l,int r){
    a[u].l=l; a[u].r=r;
    if(l<r) build(ls,l,mid),build(rs,mid+1,r);
}
void add(int u,int pos,int del){
    if(a[u].l==a[u].r) a[u].mx+=del;
    else{
        if(pos<=mid) add(ls,pos,del);
        else add(rs,pos,del);
        a[u].mx=max(a[ls].mx,a[rs].mx);
    }
}
void query(int u){
    if(a[u].l==a[u].r){
        if(a[u].mx) pos=a[u].l;
        return;
    }
    if(a[ls].mx>=a[rs].mx) query(ls);
    else query(rs);
}
int main(){
    n=read(); m=read(); build(1,1,m);
    for(rg int i=1;i<=m;i++){
        int x=read(),y=read()+1,k=read();
        r[i]=(rec){x,k,1}; r[i+m]=(rec){y,k,-1};
    }
    sort(r+1,r+1+(m<<1),cmp);
    int now=0;
    for(rg int i=1;i<=n;i++){
        while(r[++now].pos==i) add(1,r[now].k,r[now].type); now--;
        pos=-1;
        query(1);
        printf("%d\n",pos);
    }
    return 0;
}

  

#include<cstdio>
#include<algorithm>
#define rg register
#define ls (u<<1)
#define rs (u<<1|1)
#define mid ((a[u].l+a[u].r)>>1)
#define N (400010)
using namespace std;
int n,m,tot,pos,del,last[N];
struct opt{
    int pos,del,pre;
}e[N<<1];
struct tree{
    int l,r,mx;
}a[N];
inline int read(){
    int k=0,f=1; char c=getchar();
    while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
    while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar();
    return k*f;
}
inline int max(int x,int y){return x>y?x:y;}
inline void add(int x,int y,int z){e[++tot]=(opt){y,z,last[x]}; last[x]=tot;}
void build(int u,int l,int r){
    a[u].l=l; a[u].r=r;
    if(l<r) build(ls,l,mid),build(rs,mid+1,r);
}
void update(int u){
    if(a[u].l==a[u].r){a[u].mx+=del; return;}
    update(pos<=mid?ls:rs);
    a[u].mx=max(a[ls].mx,a[rs].mx);
}
void query(int u){
    if(a[u].l==a[u].r){
        if(a[u].mx) pos=a[u].l;
        return;
    }
    query(a[ls].mx>=a[rs].mx?ls:rs);
}
int main(){
    n=read(); m=read(); build(1,1,m);
    for(rg int i=1,l,r,d;i<=m;i++) l=read(),r=read(),add(l,d=read(),1),add(r+1,d,-1);
    for(rg int i=1;i<=n;i++){
        for(rg int j=last[i];j;j=e[j].pre) pos=e[j].pos,del=e[j].del,update(1);
        pos=-1; query(1); printf("%d\n",pos);
    }
    return 0;
}

  

posted @ 2018-02-11 16:07  Driver_Lao  阅读(200)  评论(0编辑  收藏  举报