【BZOJ 1901】Zju2112 Dynamic Rankings &&【COGS 257】动态排名系统 树状数组套线段树
外面是树状数组,里面是动态开点线段树,对于查询我们先把有关点找出来,然后一起在线段树上行走,这样就是单个O(log2)的了
#include <cstdio> #include <vector> #include <cstring> #define R register #define Inf 1000000000 #define MAXN 50000 using namespace std; inline int read() { R int sum=0; R char ch=getchar(); while(ch<'0'||ch>'9')ch=getchar(); while(ch>='0'&&ch<='9') { sum=(sum<<1)+(sum<<3)+ch-'0'; ch=getchar(); } return sum; } struct Seg_Tree { Seg_Tree *ch[2]; int l,r,size; void pushup() { size=ch[0]->size+ch[1]->size; } }*null,*root[MAXN+10]; typedef vector<Seg_Tree*> S; char s[1]; int a[MAXN+10]; inline Seg_Tree *New(int l,int r) { Seg_Tree *p=new Seg_Tree; p->l=l,p->r=r,p->size=0; p->ch[0]=p->ch[1]=null; return p; } int n,m; void ins(Seg_Tree *p,int key) { if(p->l==p->r) { p->size++; return; } if(key<=((p->l+p->r)>>1)) { if(p->ch[0]==null)p->ch[0]=New(p->l,((p->l+p->r)>>1)); ins(p->ch[0],key); } else { if(p->ch[1]==null)p->ch[1]=New(((p->l+p->r)>>1)+1,p->r); ins(p->ch[1],key); } p->pushup(); } inline void Ins(int pos,int key) { while(pos<=n) { if(root[pos]==null)root[pos]=New(0,Inf); ins(root[pos],key); pos+=pos&(-pos); } } void del(Seg_Tree *&p,int key) { if(p->l==p->r) { p->size--; if(p->size==0){ delete p; p=null; } return; } if(key<=((p->l+p->r)>>1))del(p->ch[0],key); else del(p->ch[1],key); p->pushup(); if(p->size==0){ delete p; p=null; } } inline void Del(int pos,int key) { while(pos<=n) { del(root[pos],key); pos+=pos&(-pos); } } inline void Init() { null=New(0,0),n=read(),m=read(); null->ch[0]=null->ch[1]=null; for(R int i=1;i<=n;i++)root[i]=null; for(R int i=1;i<=n;i++) a[i]=read(),Ins(i,a[i]); } inline S Catch(int pos) { S v;v.clear(); while(pos) { v.push_back(root[pos]); pos-=pos&(-pos); } return v; } inline S get_ch0(S v) { for(R int i=0;i<v.size();++i)v[i]=v[i]->ch[0]; return v; } inline S get_ch1(S v) { for(R int i=0;i<v.size();++i)v[i]=v[i]->ch[1]; return v; } int query(S v1,S v2,int k,int z,int y) { if(z==y)return z; R int sum=0; for(int i=0;i<v2.size();i++)sum+=v2[i]->ch[0]->size; for(int i=0;i<v1.size();i++)sum-=v1[i]->ch[0]->size; if(sum>=k) return query(get_ch0(v1),get_ch0(v2),k,z,(z+y)>>1); else return query(get_ch1(v1),get_ch1(v2),k-sum,((z+y)>>1)+1,y); } inline void Work() { R int x,y,z; while(m--) { scanf("%s",s); if(s[0]=='C') { x=read(),y=read(); Del(x,a[x]),Ins(x,y); a[x]=y; continue; } else { x=read(),y=read(),z=read(); printf("%d\n",query(Catch(x-1),Catch(y),z,0,Inf)); } } } void CL(Seg_Tree *p) { if(p==null)return; CL(p->ch[0]); CL(p->ch[1]); delete p; } inline void Clear() { for(int i=1;i<=n;i++)CL(root[i]),root[i]=NULL; delete null;null=NULL; } int main() { freopen("dynrank.in","r",stdin); freopen("dynrank.out","w",stdout); R int T=read(); while(T--) { Init(); Work(); Clear(); } }
苟利国家生死以, 岂因祸福避趋之。