bzoj1901 Zju2112 Dynamic Rankings*

bzoj1901 Zju2112 Dynamic Rankings

题意:

维护数据结构,支持区间第k大和单点修改。序列大小,操作数≤10000

题解:

构造一个树状数组,树状数组中的节点用主席树维护。一开始先插入序列中的节点,然后对于修改,就是将经过的树状数组上的主席树删除旧值,再插入新值;对于查询,还是和普通主席树一样二分,但此时的前缀和是由树状数组中数棵主席树查询节点的和得到的。反思:空间复杂度粗略计算是O(nlog^2n),常数大概是乘个7,8,在bzoj上内存达到了80M,幸好bzoj上空间给的是128M,听说原题空间是31M,规模是30000,我要是做原题早挂了!不知道怎么办QAQ

代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #define inc(i,j,k) for(int i=j;i<=k;i++)
 5 #define maxn 10010
 6 #define lb(x) x&-x
 7 using namespace std;
 8 
 9 inline int read(){
10     char ch=getchar(); int f=1,x=0;
11     while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
12     while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
13     return f*x;
14 }
15 int n,m,a[maxn],v[maxn*2],tot,root[maxn],sz[3*maxn*15*15],ch[3*maxn*15*15][2],cnt;
16 struct ask{char opt[3]; int l,r,k;}; ask asks[maxn];
17 struct ls{int id,v;}; ls lss[maxn*2]; int lsss;
18 bool cmp(ls a,ls b){return a.v<b.v;}
19 void lisan(){
20     inc(i,1,n)lss[++lsss]=(ls){i,a[i]};
21     inc(i,1,m)if(asks[i].opt[0]=='C')lss[++lsss]=(ls){n+i,asks[i].k};
22     sort(lss+1,lss+1+lsss,cmp);
23     inc(i,1,lsss){
24         if(i==1||lss[i].v!=lss[i-1].v)tot++,v[tot]=lss[i].v;
25         if(lss[i].id<=n)a[lss[i].id]=tot;else asks[lss[i].id-n].k=tot;
26     }
27 }
28 int build(int l,int r){
29     int x=++cnt; sz[x]=0; if(l==r)return x;
30     int mid=(l+r)>>1; ch[x][0]=build(l,mid); ch[x][1]=build(mid+1,r); return x;
31 }
32 void updseg(int &x,int y,int l,int r,int a){
33     cnt++; ch[cnt][0]=ch[x][0]; ch[cnt][1]=ch[x][1]; sz[cnt]=sz[x]+a; x=cnt; if(l==r)return;
34     int mid=(l+r)>>1; if(y<=mid)updseg(ch[x][0],y,l,mid,a); if(y>mid)updseg(ch[x][1],y,mid+1,r,a);
35 }
36 int queryseg(int x,int ql,int qr,int l,int r){
37     if(ql<=l&&r<=qr)return sz[x]; int mid=(l+r)>>1,q=0;
38     if(ql<=mid)q+=queryseg(ch[x][0],ql,qr,l,mid); if(mid<qr)q+=queryseg(ch[x][1],ql,qr,mid+1,r);
39     return q;
40 }
41 void updbit(int x,int y,int a){
42     while(x<=n)updseg(root[x],y,1,tot,a),x+=lb(x);
43 }
44 int querybit(int x,int ql,int qr){
45     int q=0; while(x>=1)q+=queryseg(root[x],ql,qr,1,tot),x-=lb(x); return q;
46 }
47 void init(){
48     int x=build(1,tot); inc(i,1,n)root[i]=x; inc(i,1,n)updbit(i,a[i],1);
49 }
50 int query(int ql,int qr,int k){
51     int l=1,r=tot;
52     while(1){
53         int mid=(l+r)>>1; int x=querybit(qr,l,mid)-querybit(ql-1,l,mid);
54         if(x>=k)r=mid;else l=mid+1,k-=x; if(l==r)return l;
55     }
56 }
57 void modify(int x,int y){
58     updbit(x,a[x],-1); updbit(x,y,1); a[x]=y;
59 }
60 int main(){
61     n=read(); m=read(); inc(i,1,n)a[i]=read();
62     inc(i,1,m){
63         scanf("%s",asks[i].opt);
64         if(asks[i].opt[0]=='Q')asks[i].l=read(),asks[i].r=read(),asks[i].k=read();
65         if(asks[i].opt[0]=='C')asks[i].l=read(),asks[i].k=read();
66     }
67     lisan(); init();
68     inc(i,1,m){
69         if(asks[i].opt[0]=='Q')printf("%d\n",v[query(asks[i].l,asks[i].r,asks[i].k)]);
70         if(asks[i].opt[0]=='C')modify(asks[i].l,asks[i].k);
71     }
72     return 0;
73 }

 

20160813

posted @ 2016-08-16 21:30  YuanZiming  阅读(129)  评论(0编辑  收藏  举报