• 洛谷 省选营题目 过年


    【题解】

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

      我们先把区间操作差分,变成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
    ",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
    ",pos);
        }
        return 0;
    }
    

      

  • 相关阅读:
    菜根谭#39
    菜根谭#38
    菜根谭#37
    菜根谭#36
    菜根谭#35
    菜根谭#34
    菜根谭#33
    菜根谭#32
    mysqli的使用
    mysql常用修改创建语句
  • 原文地址:https://www.cnblogs.com/DriverLao/p/8442421.html
Copyright © 2020-2023  润新知