题意:
给出长度为n的数列,m次操作
操作分为 1 x y 将x位置的数改成y
2 x y k 查询【x , y】区间内的第k小数
分析:
有了POJ 2104 那题的静态整体二分的基础后就非常好做了
还是离线处理的方法,将所有数据读入然后再整体二分
对于修改操作,将它分为删除操作和添加操作,仔细想想,这样做并不影响整体二分的结果,因为一次修改操作只对后面的有影响,而后面的影响会随着二分消除掉。
要注意一点,由于修改操作改为了两种操作,所以总空间应该开到 n+2*m
#include<cstring> #include<cstdio> #include<iostream> #include<algorithm> using namespace std; #define INF 0x3f3f3f3f #define maxn 320000 struct node { int val,l,r,k; int index,kind; } q[maxn],q1[maxn],q2[maxn]; int n,m; int a[maxn]; int c[maxn]; int ans[maxn]; inline int lowbit(int x) { return x&-x; } inline void update(int x,int val) { for(; x<=n; x+=lowbit(x)) c[x]+=val; } inline int query(int x) { int sum=0; for(; x>0; x-=lowbit(x)) sum+=c[x]; return sum; } void divide(int s,int t,int l,int r) { if(s>t) return ; if(l==r) { for(int i=s; i<=t; i++) { if(q[i].kind==2) { ans[q[i].index]=l; } } return ; } int mid=(l+r)>>1; int num1=0,num2=0; int flag1=0,flag2=0; for(int i=s; i<=t; i++) { if(q[i].kind==2) { int tmp=query(q[i].r)-query(q[i].l-1); if(tmp>=q[i].k) q1[num1++]=q[i],flag1=1; else q[i].k-=tmp,q2[num2++]=q[i],flag2=1; } else { if(q[i].val<=mid) update(q[i].index,q[i].kind),q1[num1++]=q[i]; else q2[num2++]=q[i]; } } for(int i=s; i<=t; i++) { if(q[i].kind!=2) { if(q[i].val<=mid) update(q[i].index,-q[i].kind); } } for(int i=0; i<num1; i++) q[s+i]=q1[i]; for(int i=0; i<num2; i++) q[s+num1+i]=q2[i]; if(flag1) divide(s,s+num1-1,l,mid); if(flag2) divide(s+num1,t,mid+1,r); } int main() { while(scanf("%d",&n)!=EOF) { memset(c,0,sizeof c); int cnt=1; int mm=0; for(int i=1; i<=n; i++) { scanf("%d",&a[i]); q[cnt].val=a[i]; q[cnt].index=i; q[cnt].kind=1; cnt++; } scanf("%d",&m); int num=0; for(int i=1; i<=m; i++) { int op; scanf("%d",&op); if(op==2) { int l,r,k; scanf("%d%d%d",&l,&r,&k); q[cnt].l=l; q[cnt].r=r; q[cnt].k=k; q[cnt].kind=2; q[cnt].index=num++; cnt++; } else { int x,val; scanf("%d%d",&x,&val); q[cnt].val=a[x]; q[cnt].index=x; q[cnt].kind=-1; cnt++; q[cnt].index=x; q[cnt].val=val; q[cnt].kind=1; cnt++; a[x]=val; } } divide(1,cnt-1,1,INF); for(int i=0; i<num; i++) { printf("%d\n",ans[i]); } } }