zoukankan      html  css  js  c++  java
  • 【Luogu】P2617Dynamic Ranking(树状数组套主席树)

      题目链接

      树状数组套主席树有点难懂qwq  不好理解

      树状数组套主席树的直观理解应该是:树状数组的每一个节点是一棵主席树。

      普通区间修改我们是创建1个线段树,树状数组套主席树的时候我们就创建log个线段树。

      普通区间查询我们是把from-1 和to 两个线段树作差,树状数组套主席树的时候我们就把from-1的前缀和的log个线段树和to的log个线段树作差。

      比较玄学qwq   我好像现在还是没懂

      放上代码吧

      

    #include<cctype>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cstdio>
    #define mid ((l+r)>>1)
    #define maxn 10005
    
    using namespace std;
    
    inline long long read(){
        long long num=0,f=1;
        char ch=getchar();
        while(!isdigit(ch)){
            if(ch=='-')    f=-1;
            ch=getchar();
        }
        while(isdigit(ch)){
            num=num*10+ch-'0';
            ch=getchar();
        }
        return num*f;
    }
    
    inline int low(int i){    return i&(-i);    }
    
    int s[maxn*2],q[maxn*2];
    int rt[maxn*20*20];
    int sum[maxn*20*20];
    int ls[maxn*20*20];
    int rs[maxn*20*20];
    int d[maxn],w[maxn],tot,n,m,size,point,totd,totw;
    
    void build(int &o,int l,int r){
        o=++tot;
        if(l==r)    return;
        build(ls[o],l,mid);
        build(rs[o],mid+1,r);
    }
    
    void update(int &o,int l,int r,int last,int p,int val){
        o=++tot;    ls[o]=ls[last];    rs[o]=rs[last];    sum[o]=sum[last]+val;
        if(l==r)    return;
        if(p<=mid)    update(ls[o],l,mid,ls[last],p,val);
        else        update(rs[o],mid+1,r,rs[last],p,val);
    }
    
    void add(int from,int val){
        int value=q[from];
        while(from<=n){
            update(rt[from],1,size,rt[from],value,val);
            from+=low(from);
        }
    }
    
    int query(int l,int r,int e){
        if(l==r)    return l;
        int cnt=0;
        for(int i=1;i<=totw;++i)    cnt+=sum[ls[w[i]]];
        for(int i=1;i<=totd;++i)    cnt-=sum[ls[d[i]]];
        if(e<=cnt){
            for(int i=1;i<=totd;++i)    d[i]=ls[d[i]];
            for(int i=1;i<=totw;++i)    w[i]=ls[w[i]];
            return query(l,mid,e);
        }
        else{
            for(int i=1;i<=totd;++i)    d[i]=rs[d[i]];
            for(int i=1;i<=totw;++i)    w[i]=rs[w[i]];
            return query(mid+1,r,e-cnt);
        }
    }
    
    struct Que{
        bool f;
        int from,to,rank;
        void add(int opt,int x,int y,int z){
            f=opt;from=x;to=y;rank=z;
        }
    }que[maxn];
    
    int main(){
        n=read(),m=read();
        for(int i=1;i<=n;++i)    s[++point]=q[i]=read();
        for(int i=1;i<=m;++i){
            char ch[10];int x,y;
            scanf("%s%d%d",ch,&x,&y);
            if(ch[0]=='Q'){
                int z=read();
                que[i].add(0,x,y,z);
            }
            else{
                que[i].add(1,x,y,0);
                s[++point]=y;
            }
        }
        sort(s+1,s+point+1);
        size=unique(s+1,s+point+1)-s-1;
        for(int i=1;i<=n;++i)    q[i]=lower_bound(s+1,s+size+1,q[i])-s;
        for(int i=1;i<=m;++i)
            if(que[i].f)    que[i].to=lower_bound(s+1,s+size+1,que[i].to)-s;
        //build(rt[0],1,size);
        for(int i=1;i<=n;++i)    add(i,1);
        for(int i=1;i<=m;++i){
            bool f=que[i].f;int from=que[i].from,to=que[i].to,rank=que[i].rank;
            if(f){
                add(from,-1);    q[from]=to;    add(from,1);
            }
            else{
                totd=totw=0;
                for(int j=from-1;j;j-=low(j))    d[++totd]=rt[j];
                for(int j=to;j;j-=low(j))        w[++totw]=rt[j];
                printf("%d
    ",s[query(1,size,rank)]);
            }
        }
        return 0;
    }
  • 相关阅读:
    返回一个整数数组中最大子数组的和 1
    软件工程第一周开课博客
    体温上报系统总结
    Android 布局中如何使控件居中
    Android:Unable to find explicit activity class报错
    Android Studio 线性布局
    相对布局
    HTML5 video视频
    阅读笔记——《人月神话》
    体温汇报系统界面
  • 原文地址:https://www.cnblogs.com/cellular-automaton/p/8175769.html
Copyright © 2011-2022 走看看