zoukankan      html  css  js  c++  java
  • [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
    ",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;
    }
  • 相关阅读:
    制作 MarkText 的导航栏和动画背景
    某雅互动静态页面
    html5 拖拽及用 js 实现拖拽
    九宫格
    phaser3 入门实例——收集星星游戏
    Flexbox Froggy:练习 Flex 布局的小游戏
    JS30
    ElasticSearch
    JVM
    jstack命令的使用
  • 原文地址:https://www.cnblogs.com/bluefly-hrbust/p/11512566.html
Copyright © 2011-2022 走看看