zoukankan      html  css  js  c++  java
  • 【BZOJ】【1901】【Zju2112】 Dynamic Rankings

    再填个坑。

     动态维护区间第K大(带单点修改)

      首先裸的区间第K大我们是用的【前缀和】思想,实现O(n)预处理,O(1)找树查询,那么如果是动态的呢?我们可以利用树状数组(BIT)的思想,进行O(logn)的修改,O(logn)的查询(当然由于是在线段树上做,都各需要再乘logn的复杂度)

      也就是说,每次修改,一块改logn棵线段树;每次查询也是在logn棵线段树上一起往下找!

      P.S.本题需将所有数(包括修改后的数)进行离散化

      1 //BZOJ 1901
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<cstdlib>
      5 #include<iostream>
      6 #include<algorithm>
      7 #define rep(i,n) for(int i=0;i<n;++i)
      8 #define F(i,j,n) for(int i=j;i<=n;++i)
      9 #define D(i,j,n) for(int i=j;i>=n;--i)
     10 #define lowbit(x) ((x)&(-(x)))
     11 using namespace std;
     12 const int N=110086;
     13 
     14 struct Tree{
     15     int cnt,l,r;
     16 }t[N*30];
     17 int n,m,num=0,root[N],a[N>>1],b[N],dat[N>>1][4],size=0,cnt=0;
     18 int lc,rc,ln[N],rn[N];
     19 
     20 #define mid (l+r>>1)
     21 void build(int &o,int l,int r){
     22     o=++cnt; t[o].cnt=0;
     23     if (l==r) return;
     24     build(t[o].l,l,mid);
     25     build(t[o].r,mid+1,r);
     26 }
     27 
     28 void updata(int &o,int l,int r,int pos,int val){
     29     t[++cnt]=t[o],o=cnt,t[o].cnt+=val;
     30     if (l==r) return;
     31     if (pos <= mid) updata(t[o].l,l,mid,pos,val);
     32     else updata(t[o].r,mid+1,r,pos,val);
     33 }
     34 
     35 void modify(int x,int pos,int val){
     36     for(x;x<=n;x+=lowbit(x) )//一次改logn棵树
     37         updata(root[x],1,num,pos,val);
     38 }
     39 
     40 int query(int i,int j,int rank){
     41     int l=1,r=num;
     42     int tl=0,tr=0;
     43     
     44     while(l!=r){
     45         tl=tr=0;
     46         F(i,1,lc) tl+=t[t[ln[i]].l].cnt;//将logn棵树的和加出来
     47         F(i,1,rc) tr+=t[t[rn[i]].l].cnt;
     48         if (tr-tl>=rank){
     49             F(i,1,lc) ln[i]=t[ln[i]].l;//向左找
     50             F(i,1,rc) rn[i]=t[rn[i]].l;
     51             r=mid;
     52         }
     53         else{
     54             F(i,1,lc) ln[i]=t[ln[i]].r;//向右找
     55             F(i,1,rc) rn[i]=t[rn[i]].r;
     56             l=mid+1; rank-=tr-tl; 
     57         }
     58         
     59     }
     60     return l;
     61 }
     62 #undef mid
     63 int getans(int l,int r,int k){
     64     rc=lc=0;
     65     for(r;r;r-=lowbit(r))
     66         rn[++rc]=root[r];
     67     for(l;l;l-=lowbit(l))
     68         ln[++lc]=root[l];
     69     return query(1,num,k);
     70 }
     71 
     72 void solve(){
     73     sort(b+1,b+size+1);
     74     num=unique(b+1,b+size+1)-b-1;//这个神奇的用法……是什么意思?
     75     F(i,1,n) a[i]=lower_bound(b+1,b+num+1,a[i])-b;
     76     build(root[0],1,num);
     77     F(i,1,n) modify(i,a[i],1);
     78     F(i,1,m){
     79         if(dat[i][0]==0) printf("%d
    ",b[ getans(dat[i][1]-1,dat[i][2],dat[i][3]) ]);
     80         else{
     81             int pos=lower_bound(b+1,b+num+1,dat[i][2])-b;
     82             modify(dat[i][1],a[dat[i][1]],-1);
     83             a[dat[i][1]]=pos;
     84             modify(dat[i][1],a[dat[i][1]],1);
     85         }
     86     }
     87 }
     88 
     89 int main(){
     90     #ifndef ONLINE_JUDGE
     91     freopen("file.in","r",stdin);
     92     #endif
     93     int T=1;
     94 //    scanf("%d",&T);
     95     while(T--){
     96         size=cnt=num=0;
     97         memset(b,0,sizeof b);
     98         memset(t,0,sizeof t);
     99         memset(dat,0,sizeof dat);
    100         scanf("%d%d",&n,&m);
    101         F(i,1,n){
    102             scanf("%d",&a[i]);
    103             b[++size]=a[i];
    104         }
    105         char cmd[3];
    106         F(i,1,m){
    107             scanf("%s",cmd);
    108             if (cmd[0]=='C'){
    109                 dat[i][0]=1;
    110                 scanf("%d%d",&dat[i][1],&dat[i][2]);
    111                 b[++size]=dat[i][2];
    112             }
    113             else{
    114                 dat[i][0]=0;
    115                 scanf("%d%d%d",&dat[i][1],&dat[i][2],&dat[i][3]);
    116             }
    117         }
    118         solve();
    119     }
    120     return 0;
    121 }
    122 /************************************************** 
    123 利用BIT的思想,实现前缀-差分的logn的转化
    124 裸的可持久化线段树是每棵树维护一个区间[1,i](前缀和) 
    125 查询O(1),而修改就需要 O(n)了
    126 而动态进行修改&查询-->BIT里套一个可持久化线段树
    127 BIT的每个节点表示原数组的一个区间
    128 然后用可持久化线段树来维护这个区间 
    129 查询的时候log(n)棵线段树一起查
    130 **************************************************/ 
    View Code
  • 相关阅读:
    codesmith+mysql生成代码
    遭遇笔试
    线性是一种简洁,简洁就是美
    Microsoft Kinect SDK vs PrimeSense OpenNI
    资料收集:让OpenCV使用IPP
    提纲
    在PC上安装使用Kinect
    OpenNI设置Kinect帧率,读取IR图
    cout,rather than printf
    单步调试时,getnextframe会失败。又
  • 原文地址:https://www.cnblogs.com/Tunix/p/4197745.html
Copyright © 2011-2022 走看看