码迷,mamicode.com
首页 > 其他好文 > 详细

[主席树]ZOJ2112 Dynamic Rankings

时间:2015-07-19 23:25:41      阅读:157      评论:0      收藏:0      [点我收藏+]

标签:

题意:n个数,q个询问 (n<=50000, q<=10000)

Q x y z 代表询问[x, y]区间里的第z小的数

C x y    代表将(从左往右数)第x个数变成y

 

上篇介绍了在[x, y]区间内查询第z小的数的方法(静态主席树)

本题有更新操作

 

若仍用上篇的做法,

每次更新一个数,需要更新的是T[i], T[i+1]... ...T[n](该数所在的树以及它后面的所有树)

因为每棵树T[i]所记录的都是前缀(1到i的数出现的次数) 因此,改变i,会影响i到n的所有树

这样,每次更新的复杂度最坏为O(n),最坏更新q次即为O(n*m) 复杂度相当庞大,很明显这样做是不行的

 

那怎么办呢?

我们可以发现,对于改变i处的数这个操作,对于T[i], T[i+1]... ...T[n]这些树的影响是相同的

  都只改变了  “原来i处的数 的数量”  和  “现在i处的数 的数量” 这两个值而已

因此,我们要用主席树来维护每个位置,对于每个位置建立线段树,(而非每个位置及其前缀)

再用树状数组来记录更新,维护前缀和,每次更新logn棵树

 

将每个位置建一棵线段树的好处是 使得每个位置可以相加减,那么就相当于用树状数组来询问区间和了

 

 

模板是kuangbin

query用非递归的形式节约时间orz...

技术分享
  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], wz[N];
  8 int T[N], L[N<<5], R[N<<5], c[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[10010];
 16 
 17 int build(int l, int r)
 18 {
 19     int rt=tot++;
 20     c[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 Insert(int rt, int pos, int val)
 31 {
 32     int newrt=tot, tmp=tot++;
 33     int l=0, r=m-1;
 34     c[newrt]=c[rt]+val;
 35     while(l<r)
 36     {
 37         int m=(l+r)>>1;
 38         if(pos<=m)
 39         {
 40             L[newrt]=tot++;
 41             R[newrt]=R[rt];
 42             newrt=L[newrt];
 43             rt=L[rt];
 44             r=m;
 45         }
 46         else
 47         {
 48             R[newrt]=tot++;
 49             L[newrt]=L[rt];
 50             newrt=R[newrt];
 51             rt=R[rt];
 52             l=m+1;
 53         }
 54         c[newrt]=c[rt]+val;
 55     }
 56     return tmp;
 57 }
 58 
 59 int lowbit(int x)
 60 {
 61     return x&(-x);
 62 }
 63 
 64 int use[N];
 65 void add(int x, int pos, int val)
 66 {
 67     while(x<=n)
 68     {
 69         S[x]=Insert(S[x], pos, val);
 70         x+=lowbit(x);
 71     }
 72 }
 73 
 74 int sum(int x)
 75 {
 76     int ret=0;
 77     while(x>0)
 78     {
 79         ret+=c[L[use[x]]];
 80         x-=lowbit(x);
 81     }
 82     return ret;
 83 }
 84 
 85 int query(int left, int right, int k)
 86 {
 87     int lrt=T[left-1];
 88     int rrt=T[right];
 89     int l=0, r=m-1;
 90     for(int i=left-1;i;i-=lowbit(i))
 91         use[i]=S[i];
 92     for(int i=right;i;i-=lowbit(i))
 93         use[i]=S[i];
 94     while(l<r)
 95     {
 96         int m=(l+r)>>1;
 97         int tmp=sum(right)-sum(left-1)+c[L[rrt]]-c[L[lrt]];
 98         if(tmp>=k)
 99         {
100             r=m;
101             for(int i=left-1;i;i-=lowbit(i))
102                 use[i]=L[use[i]];
103             for(int i=right;i;i-=lowbit(i))
104                 use[i]=L[use[i]];
105             lrt=L[lrt];
106             rrt=L[rrt];
107         }
108         else
109         {
110             l=m+1;
111             k-=tmp;
112             for(int i=left-1;i;i-=lowbit(i))
113                 use[i]=R[use[i]];
114             for(int i=right;i;i-=lowbit(i))
115                 use[i]=R[use[i]];
116             lrt=R[lrt];
117             rrt=R[rrt];
118         }
119     }
120     return l;
121 }
122 
123 void Modify(int x, int p, int d)
124 {
125     while(x<=n)
126     {
127         S[x]=Insert(S[x], p, d);
128         x+=lowbit(x);
129     }
130 }
131 
132 int main()
133 {
134     int t;
135     scanf("%d", &t);
136     while(t--)
137     {
138         int q;
139         scanf("%d%d", &n, &q);
140         tot=0;
141         m=0;
142         for(int i=1;i<=n;i++)
143         {
144             scanf("%d", &a[i]);
145             wz[m++]=a[i];
146         }
147         for(int i=0;i<q;i++)
148         {
149             char s[10];
150             scanf("%s", s);
151             if(s[0]==Q)
152             {
153                 scanf("%d%d%d", &op[i].l, &op[i].r, &op[i].k);
154                 op[i].Q=1;
155             }
156             else
157             {
158                 scanf("%d%d", &op[i].l, &op[i].r);
159                 op[i].Q=0;
160                 wz[m++]=op[i].r;
161             }
162         }
163         sort(wz, wz+m);
164         int mm=unique(wz, wz+m)-wz;
165         m=mm;
166         T[0]=build(0, m-1);
167         for(int i=1;i<=n;i++)
168             T[i]=Insert(T[i-1], lower_bound(wz, wz+m, a[i])-wz, 1);
169         for(int i=1;i<=n;i++)
170             S[i]=T[0];
171         for(int i=0;i<q;i++)
172         {
173             if(op[i].Q)
174                 printf("%d\n", wz[query(op[i].l, op[i].r, op[i].k)]);
175             else
176             {
177                 Modify(op[i].l, lower_bound(wz, wz+m, a[op[i].l])-wz, -1);
178                 Modify(op[i].l, lower_bound(wz, wz+m, op[i].r)-wz, 1);
179                 a[op[i].l]=op[i].r;
180             }
181         }
182     }
183     return 0;
184 }
ZOJ 2112

 

[主席树]ZOJ2112 Dynamic Rankings

标签:

原文地址:http://www.cnblogs.com/Empress/p/4659824.html

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