[主席樹]ZOJ2112 && BZOJ1901 Dynamic Rankings

題意:n個數,q個詢問 (n<=50000, q<=10000)html

Q x y z 表明詢問[x, y]區間裏的第z小的數node

C x y    表明將(從左往右數)第x個數變成yc++

 

上篇介紹了在[x, y]區間內查詢第z小的數的方法(靜態主席樹)數組

本題有更新操做ide

 

若仍用上篇的作法,ui

每次更新一個數,須要更新的是T[i], T[i+1]... ...T[n](該數所在的樹以及它後面的全部樹)spa

由於每棵樹T[i]所記錄的都是前綴(1到i的數出現的次數) 所以,改變i,會影響i到n的全部樹3d

這樣,每次更新的複雜度最壞爲O($n$),最壞更新q次即爲O($n\times m$) 複雜度至關龐大,很明顯這樣作是不行的code

 

那怎麼辦呢?htm

咱們能夠發現,對於改變i處的數這個操做,對於T[i], T[i+1]... ...T[n]這些樹的影響是相同的

  都只改變了  「原來i處的數 的數量」  和  「如今i處的數 的數量」 這兩個值而已

咱們只要在原來的基礎上增長一類樹, 用它們來維護更新掉的數

即用樹狀數組來記錄更新,每次更新$logn$棵樹

 

下面來演示一下建樹到查詢的過程:

好比此題的第一個案例

5 3
3 2 1 4 7
Q 1 4 3
C 2 6
Q 2 5 3

先將序列以及要更新的數(C操做)離散化  

即3 2 1 4 7 、 6  ---->(排序) ----> 1 2 3 4 6 7  

那麼咱們就須要建一棵這樣的樹:

(圈裏的都是結點的編號, 四、五、六、九、十、11號結點表明的分別是一、二、三、四、六、7)

(四、五、九、10你也能夠任意做爲6或11的兒子, 遞歸生成的是相似這樣的, 這並不重要)

 

對於3 2 1 4 7(先無論須要更新的6)建完樹見下圖(建樹過程同靜態的,不明白的戳這裏,上篇博客有講)

(紅色的是個數, 相同結點的個數省略了,同前一棵樹)

 

對於C操做以前的Q,就跟靜態的相似,減一減 找就行了

 

而後下面要更新了

對於更新, 咱們不改變這些已經建好的樹, 而是另建一批樹S,用來記錄更新,而這批線段樹,咱們用樹狀數組來維護

也就是樹狀數組的每一個節點都是一顆線段樹

一開始,S[0]、S[1]、S[2]、S[3]、S[4]、S[5](樹狀數組的每一個節點)這些都與T[0]相同(也就是每一個節點建了一棵空樹)

對於C 2 6 這個操做, 咱們只須要減去一個2,加上一個6便可

對於減去2

(樹狀數組i+lowbit(i)爲i的父親節點, 修改i,就要把i的全部父親節點都修改了)

2在樹狀數組中出現的位置是 二、2+lowbit(2)=4 這兩個位置,    

所以要更新的是S[2]和S[4]這兩個節點中的樹

刪去2後是這樣

加上一個6 (一樣是對於2號位置, 所以須要更新的還是S[2]和S[4])

加上以後是這樣

 

 

 當查詢的時候, 對樹T的操做與靜態的一致,另外再加上S樹的值就行了

 

 

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 typedef long long LL;
  4 #define lson l, m
  5 #define rson m+1, r
  6 const int N=60005;
  7 int a[N], Hash[N];
  8 int T[N], L[N<<5], R[N<<5], sum[N<<5];
  9 int S[N];
 10 int n, m, tot;
 11 struct node
 12 {
 13     int l, r, k;
 14     bool Q;
 15 }op[10005];
 16 
 17 int build(int l, int r)
 18 {
 19     int rt=(++tot);
 20     sum[rt]=0;
 21     if(l!=r)
 22     {
 23         int m=(l+r)>>1;
 24         L[rt]=build(lson);
 25         R[rt]=build(rson);
 26     }
 27     return rt;
 28 }
 29 
 30 int update(int pre, int l, int r, int x, int val)
 31 {
 32     int rt=(++tot);
 33     L[rt]=L[pre], R[rt]=R[pre], sum[rt]=sum[pre]+val;
 34     if(l<r)
 35     {
 36         int m=(l+r)>>1;
 37         if(x<=m)
 38             L[rt]=update(L[pre], lson, x, val);
 39         else
 40             R[rt]=update(R[pre], rson, x, val);
 41     }
 42     return rt;
 43 }
 44 
 45 int lowbit(int x)
 46 {
 47     return x&(-x);
 48 }
 49 
 50 int use[N];
 51 void add(int x, int pos, int val)
 52 {
 53     while(x<=n)
 54     {
 55         S[x]=update(S[x], 1, m, pos, val);
 56         x+=lowbit(x);
 57     }
 58 }
 59 
 60 int Sum(int x)
 61 {
 62     int ret=0;
 63     while(x>0)
 64     {
 65         ret+=sum[L[use[x]]];
 66         x-=lowbit(x);
 67     }
 68     return ret;
 69 }
 70 
 71 int query(int u, int v, int lr, int rr, int l, int r, int k)
 72 {
 73     if(l>=r)
 74         return l;
 75     int m=(l+r)>>1;
 76     int tmp=Sum(v)-Sum(u)+sum[L[rr]]-sum[L[lr]];
 77     if(tmp>=k)
 78     {
 79         for(int i=u;i;i-=lowbit(i))
 80             use[i]=L[use[i]];
 81         for(int i=v;i;i-=lowbit(i))
 82             use[i]=L[use[i]];
 83         return query(u, v, L[lr], L[rr], lson, k);
 84     }
 85     else
 86     {
 87         for(int i=u;i;i-=lowbit(i))
 88             use[i]=R[use[i]];
 89         for(int i=v;i;i-=lowbit(i))
 90             use[i]=R[use[i]];
 91         return query(u, v, R[lr], R[rr], rson, k-tmp);
 92     }
 93 }
 94 
 95 void modify(int x, int p, int d)
 96 {
 97     while(x<=n)
 98     {
 99         S[x]=update(S[x], 1, m, p, d);
100         x+=lowbit(x);
101     }
102 }
103 
104 int main()
105 {
106     int t;
107     scanf("%d", &t);
108     while(t--)
109     {
110         int q;
111         scanf("%d%d", &n, &q);
112         tot=0;
113         m=0;
114         for(int i=1;i<=n;i++)
115         {
116             scanf("%d", &a[i]);
117             Hash[++m]=a[i];
118         }
119         for(int i=0;i<q;i++)
120         {
121             char s[10];
122             scanf("%s", s);
123             if(s[0]=='Q')
124             {
125                 scanf("%d%d%d", &op[i].l, &op[i].r, &op[i].k);
126                 op[i].Q=1;
127             }
128             else
129             {
130                 scanf("%d%d", &op[i].l, &op[i].r);
131                 op[i].Q=0;
132                 Hash[++m]=op[i].r;
133             }
134         }
135         sort(Hash+1, Hash+1+m);
136         int mm=unique(Hash+1, Hash+1+m)-Hash-1;
137         m=mm;
138         T[0]=build(1, m);
139         for(int i=1;i<=n;i++)
140             T[i]=update(T[i-1], 1, m, lower_bound(Hash+1, Hash+1+m, a[i])-Hash, 1);
141         for(int i=1;i<=n;i++)
142             S[i]=T[0];
143         for(int i=0;i<q;i++)
144         {
145             if(op[i].Q)
146             {
147                 for(int j=op[i].l-1;j;j-=lowbit(j))
148                     use[j]=S[j];
149                 for(int j=op[i].r;j;j-=lowbit(j))
150                     use[j]=S[j];
151                 printf("%d\n", Hash[query(op[i].l-1, op[i].r, T[op[i].l-1], T[op[i].r], 1, m, op[i].k)]);
152             }
153             else
154             {
155                 modify(op[i].l, lower_bound(Hash+1, Hash+1+m, a[op[i].l])-Hash, -1);
156                 modify(op[i].l, lower_bound(Hash+1, Hash+1+m, op[i].r)-Hash, 1);
157                 a[op[i].l]=op[i].r;
158             }
159         }
160     }
161     return 0;
162 }
ZOJ 2112
相關文章
相關標籤/搜索