码迷,mamicode.com
首页 > 编程语言 > 详细

【Luogu】P2617Dynamic Ranking(树状数组套主席树)

时间:2018-01-02 11:41:46      阅读:159      评论:0      收藏:0      [点我收藏+]

标签:区间修改   val   dynamic   int   type   题目   ast   add   lib   

  题目链接

  树状数组套主席树有点难懂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\n",s[query(1,size,rank)]);
        }
    }
    return 0;
}

 

【Luogu】P2617Dynamic Ranking(树状数组套主席树)

标签:区间修改   val   dynamic   int   type   题目   ast   add   lib   

原文地址:https://www.cnblogs.com/cellular-automaton/p/8175769.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!