您的位置:首页 > 其它

[bzoj1901]: Zju2112 Dynamic Rankings

2016-01-13 14:28 162 查看
  人生第一道树套树。。(虽然暑假就写了= =)

  这题是树状数组里面套个可持久化线段树。。。一开始想反了然后发现完全不会写TAT

  一般的树状数组操作的时候是直接修改数组里的值的,套上可持久化线段树后就变成在相应的那颗线段树里面修改了。

  修改操作就一个一个改,但查询第k大的时候要先把对应的线段树都存起来,然后一起算。。。

  具体见代码吧= =

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define rep1()for(register int i=1;i<=len1;i++)
#define rep2()for(register int i=1;i<=len2;i++)
using namespace std;
const int maxn=20233;
int num[maxn*17*17],lc[maxn*17*17],rc[maxn*17*17],rt[maxn];
int L[20],R[20];
struct zs{
int num,id;
}a[maxn];
struct ask{
int l,r,x;
bool id;
}q[10023];
int b[maxn],c[maxn];
int i,j,cnt,n,m,tot,len1,len2;

int ra;char rx;
inline int read(){
rx=getchar(),ra=0;
while(rx<'0'||rx>'9')rx=getchar();
while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra;
}

inline int sum1(){int sum=0;rep1()sum+=num[L[i]];return sum;}
inline int sum2(){int sum=0;rep2()sum+=num[R[i]];return sum;}

inline void run1(int x){for(len1=0;x;x-=x&(-x))L[++len1]=rt[x];}
inline void run2(int x){for(len2=0;x;x-=x&(-x))R[++len2]=rt[x];}

void ins(int pre,int &now,int l,int r,int v){
now=++tot;num[now]=num[pre]+1;
if(l==r)return;int mid=(l+r)>>1;
if(v<=mid)rc[now]=rc[pre],ins(lc[pre],lc[now],l,mid,v);
else lc[now]=lc[pre],ins(rc[pre],rc[now],mid+1,r,v);
}
int query(int l,int r,int k){
if(l==r)return l;
int mid=(l+r)>>1,lsize=0;
rep1()lsize-=num[lc[L[i]]];rep2()lsize+=num[lc[R[i]]];
if(lsize>=k){
rep1()L[i]=lc[L[i]];rep2()R[i]=lc[R[i]];
return query(l,mid,k);
}else{
rep1()L[i]=rc[L[i]];rep2()R[i]=rc[R[i]];
return query(mid+1,r,k-lsize);
}
}
void change(int pre,int &now,int l,int r,int v,bool del){
now=++tot,num[now]=num[pre]-(del?1:-1);
if(l==r)return;int mid=(l+r)>>1;
if(v<=mid)rc[now]=rc[pre],change(lc[pre],lc[now],l,mid,v,del);
else lc[now]=lc[pre],change(rc[pre],rc[now],mid+1,r,v,del);
}
void build(int l,int r,int &x){
x=++tot;
if(l==r)build(l,(l+r)>>1,lc[x]),build(((l+r)>>1)+1,r,rc[x]);
}
bool cmp(zs a,zs b){return a.num<b.num;}
int main(){
n=read(),m=read();cnt=n;
for(i=1;i<=n;i++)a[i].num=read(),a[i].id=i;char rx;
for(i=1;i<=m;i++){
for(rx=getchar();rx!='Q'&&rx!='C';rx=getchar());
q[i].id=(rx=='Q');
if(q[i].id)q[i].l=read(),q[i].r=read(),q[i].x=read();
else q[i].l=read(),a[++cnt].num=q[i].x=read(),a[cnt].id=i+n;
}
sort(a+1,a+1+cnt,cmp);int tmp=cnt;

for(i=1,cnt=0;i<=tmp;i++){
if(i==1||a[i].num!=a[i-1].num)c[++cnt]=a[i].num;
b[a[i].id]=cnt;if(a[i].id>n)q[a[i].id-n].x=cnt;
}
build(1,cnt,rt[0]);for(i=1;i<=n;i++)rt[i]=rt[0];
//  for(i=1;i<=m;i++)if(q[i].id)printf("    %d\n",q[i].x);
for(i=1;i<=n;i++)for(j=i;j<=n;j+=j&(-j))ins(rt[j],rt[j],1,cnt,b[i]);
for(i=1;i<=m;i++){
if(q[i].id){
run1(q[i].l-1),run2(q[i].r);
//      printf("    %d--%d       %d %d\n",q[i].l,q[i].r,len1,len2);
//      for(j=1;j<=len1;j++)printf("  %d",L[j]);puts("!!");for(j=1;j<=len2;j++)printf("  %d",R[j]);puts("");puts("!");
printf("%d\n",c[query(1,cnt,q[i].x)]);
}
else {
for(j=q[i].l;j<=n;j+=j&(-j))change(rt[j],rt[j],1,cnt,b[q[i].l],1);
for(j=q[i].l;j<=n;j+=j&(-j))change(rt[j],rt[j],1,cnt,q[i].x,0);
b[q[i].l]=q[i].x;
}
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: