BZOJ 1901 Dynamic Rankings (整体二分+树状数组)
题目大意:略
洛谷传送门 这道题在洛谷上数据比较强
貌似这个题比较常见的写法是树状数组套主席树,动态修改
我写的是整体二分
一开始的序列全都视为插入
对于修改操作,把它拆分成插入和删除两个操作
像$CDQ$分治一样,用结构体记录操作的位置,修改的权值等
假设为需要处理的询问分配了一个答案$mid$
查询区间第$K$小,我们只需要查询区间内权值为$[l,mid]$的数有几个
每次插入/删除,都看这次操作修改的权值是否$\in[l,mid]$
如果是,说明这个它对答案有贡献,在它在原序列的位置上$+1$,那么某个区间权值为$[l,mid]$的数就是查询前缀和,用树状数组维护
反之都是没贡献的
如果超过了$K$个,说明第$K$小的数小于等于$mid$,把它扔到左区间递归
如果小于$K$个,说明第$K$小的数一定大于$mid$,$K-=mid$,把它扔到右区间递归
插入删除操作也要按权值分左右区间递归
注意不要破坏时间序!
1 #include <vector> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #define N1 105000 6 #define M1 205000 7 #define ll long long 8 #define dd double 9 #define inf 233333333 10 using namespace std; 11 12 int gint() 13 { 14 int ret=0,fh=1;char c=getchar(); 15 while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();} 16 while(c>='0'&&c<='9'){ret=ret*10+c-'0';c=getchar();} 17 return ret*fh; 18 } 19 int n,m,nn; 20 struct BIT{ 21 int sum[N1]; 22 void update(int x,int w){ for(int i=x;i<=n;i+=(i&(-i))) sum[i]+=w; } 23 int query(int x){ int ans=0; for(int i=x;i;i-=(i&(-i))) ans+=sum[i]; return ans;} 24 void clr(int x){ for(int i=x;i<=n;i+=(i&(-i))) sum[i]=0; } 25 }s; 26 struct node{int i,j,k,t,id;}a[N1+M1],tmp[N1+M1]; 27 int w[M1],ma,que[N1+M1],tl,f[N1],c[N1],use[N1+M1]; 28 29 void alldic(int l,int r,int ql,int qr) 30 { 31 if(l>r||ql>qr) return; 32 int mid=(l+r)>>1,i,j,S=ql,E,sum; 33 for(i=ql;i<=qr;i++) 34 { 35 if(!a[i].k){ 36 if(a[i].j<=mid){ s.update(a[i].i,1); que[++tl]=a[i].i; use[i]=1; } 37 if(a[i].j<mid) tmp[S++]=a[i]; 38 }else if(a[i].k==-1){ 39 if(a[i].j<=mid){ s.update(a[i].i,-1); que[++tl]=a[i].i; use[i]=1; } 40 if(a[i].j<mid) tmp[S++]=a[i]; 41 }else{ 42 sum=s.query(a[i].j)-s.query(a[i].i-1); 43 if(sum<a[i].k){ a[i].k-=sum; } 44 else{ f[a[i].t]=w[mid]; tmp[S++]=a[i]; use[i]=1; } 45 } 46 } 47 for(i=ql,E=S;i<=qr;i++) 48 { 49 if(use[i]) use[i]=0; 50 else tmp[E++]=a[i]; 51 } 52 while(tl){ s.clr(que[tl--]); } 53 for(i=ql;i<=qr;i++) a[i]=tmp[i]; 54 alldic(l,mid-1,ql,S-1); alldic(mid+1,r,S,E-1); 55 } 56 char str[10]; 57 58 int main() 59 { 60 scanf("%d%d",&n,&m); 61 int i,j; 62 for(i=1;i<=n;i++){ nn++; a[nn].j=gint(); a[nn].i=i; w[++ma]=a[nn].j; c[i]=a[i].j; } 63 for(i=1;i<=m;i++) 64 { 65 scanf("%s",str); 66 if(str[0]=='Q'){ 67 nn++; a[nn].i=gint(); a[nn].j=gint(); a[nn].k=gint(); a[nn].t=i; 68 }else{ 69 nn++; a[nn].k=-1; a[nn].i=gint(); a[nn].j=c[a[nn].i]; 70 nn++; a[nn].k=0; a[nn].i=a[nn-1].i; a[nn].j=gint(); 71 c[a[nn].i]=a[nn].j; w[++ma]=a[nn].j; 72 } 73 f[i]=-1; 74 } 75 sort(w+1,w+ma+1); ma=unique(w+1,w+ma+1)-(w+1); 76 for(i=1;i<=nn;i++) if(a[i].k<=0) a[i].j=lower_bound(w+1,w+ma+1,a[i].j)-w; 77 alldic(1,ma,1,nn); 78 for(i=1;i<=m;i++) if(f[i]>=0) printf("%d\n",f[i]); 79 return 0; 80 }