[luogu P2617] Dynamic Rankings 带修主席树

  带修改的主席树,其实这种,已经不能算作主席树了,因为这个没有维护可持久化的。。。

  主席树直接带修改的话,由于这种数据结构是可持久化的,那么要相应改动,这个节点以后所有的主席树,这样单次修改,就达到n*log n 的复杂度

 现在介绍这种待修改的主席树,本质上是用树状数组的区间查询维护的线段树,树状数组的每个点,都开一个权值线段树,维护的是lowbit(x)-x之间的数字的出现次数

 这样我们相当于,把一个1-n权值线段树,用树状数组给砍成logn段,这样就非常方便。。。我们用树状数组遍历维护前缀和的过程,变成维护树的前缀的过程,这样单次维护的复杂度,大概为两个log,还是可以接受的

  模版题

 

#include<bits/stdc++.h>
using namespace std;
const int maxx = 2e5+6;
struct node{
  int l,r,cnt;
}tree[maxx*500];
struct query{
   int l,r,k;
}que[maxx*2];
int trl[maxx],trr[maxx],a[maxx],root[maxx];
int cnt,lenx,leny,n,sz;
vector<int>p;
void update(int l,int r,int pre,int &now,int pos,int w){
    now=++cnt;
    tree[now]=tree[pre];
    tree[now].cnt+=w;
    if (l==r)
        return ;
    int mid=(l+r)>>1;
    if (pos<=mid){
        update(l,mid,tree[pre].l,tree[now].l,pos,w);
    }else{
        update(mid+1,r,tree[pre].r,tree[now].r,pos,w);
    }
}
/**查询区间第k大**/
int query(int l,int r,int k){
   if(l==r)
      return l;
   int s=0;
   ///查询区间个数
   for (int i=1;i<=lenx;i++){
      s-=tree[tree[trl[i]].l].cnt;
   }
   for (int i=1;i<=leny;i++){
      s+=tree[tree[trr[i]].l].cnt;
   }
   int mid=(l+r)>>1;
   if(k<=s){
    ///把询问变成询问单点的左子树
      for(int i=1;i<=lenx;i++){
        trl[i]=tree[trl[i]].l;
      }
      for(int i=1;i<=leny;i++){
        trr[i]=tree[trr[i]].l;
      }
      return query(l,mid,k);
   }else {
      ///把询问变成询问单点的右子树
      for(int i=1;i<=lenx;i++){
        trl[i]=tree[trl[i]].r;
      }
      for(int i=1;i<=leny;i++){
        trr[i]=tree[trr[i]].r;
      }
      return query(mid+1,r,k-s);
   }
}
int lowbit(int x){
   return x&(-x);
}
void add(int x,int w){
   int pos=lower_bound(p.begin(),p.end(),a[x])-p.begin()+1;
   for (int i=x;i<=n;i+=lowbit(i)){
       update(1,sz,root[i],root[i],pos,w);
   }
}
int main(){
  int q;
  scanf("%d%d",&n,&q);
  cnt=0;
  for (int i=1;i<=n;i++){
    scanf("%d",&a[i]);
    p.push_back(a[i]);
  }
  for (int i=1;i<=q;i++){
     char op[3];
     scanf("%s",op);
     if(op[0]=='C'){
        scanf("%d%d",&que[i].l,&que[i].r);
        que[i].k=0;
        p.push_back(que[i].r);
     }else{
        scanf("%d%d%d",&que[i].l,&que[i].r,&que[i].k);
     }
  }
  ///把点全部离散排序
  sort(p.begin(),p.end());
  p.erase(unique(p.begin(),p.end()),p.end());
  sz=p.size();
  for (int i=1;i<=n;i++){
     add(i,1);
  }
  for (int i=1;i<=q;i++){
     if (que[i].k){
         lenx=0;leny=0;
         for (int j=que[i].r;j;j-=lowbit(j)){
            trr[++leny]=root[j];
         }
         for (int j=que[i].l-1;j;j-=lowbit(j)){
            trl[++lenx]=root[j];
         }
         printf("%d\n",p[query(1,sz,que[i].k)-1]);
     }else{
         ///前缀中删除这个树的影响
         add(que[i].l,-1);
         a[que[i].l]=que[i].r;
         add(que[i].l,1);
     }
  }
  return 0;
}

 

posted @ 2019-09-12 16:26  bluefly-hrbust  阅读(239)  评论(0编辑  收藏  举报