刚觉得最近写代码比较顺畅没什么Bug,cdq分治真是我的一个噩梦。。
整体二分模板题,带修改的区间第k小。
vjudge不知抽什么风,用不了,hdu忘了密码了一直在那里各种试,难受。。
写得比较鬼畜。
整体二分,传了三个l,r分别是二分答案的 el ,er ,对当前答案可能有贡献的修改区间的 l , r ,答案在当前二分区间中的询问区间 ql, qr
每次对el, er 取个mid,然后修改区间是按时间排好序的,按时间扫过去,在修改值大于mid的地方+1(区间第k小等价于大于等于它的数有len-k+1个),同时把这些区间往右放,其余区间往作放。
然后对于询问区间查询区间内1的个数,就知道了区间中大于等于mid的数的个数,如果个数大于等于len-k+1就把询问区间往右放,否则减去查询的值往左放。
el==er时对所有的询问区间更新答案。
注意的时我的这种鬼畜写法往右放时二分区间是mid,r,往左是l,mid-1,所以对于偶数长度的区间强制mid靠右才ok。。
跑得还蛮快的。
反正我觉得树套树优秀多了,虽然跑得慢一点。
//Achen#include#include #include #include #include #include #include #include #include const int N=300007;typedef long long LL;using namespace std;int n,m,cq,v[N],ans[N];template void read(T &x) { char ch=getchar(); x=0; T f=1; while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar(); if(ch=='-') f=-1,ch=getchar(); for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;}struct node { int ti,pos,v,f; node(){} node(int ti,int pos,int v,int f):ti(ti),pos(pos),v(v),f(f){}}cg[N],tp[N];struct qs{ int id,ti,l,r,k; qs(){} qs(int id,int ti,int l,int r,int k):id(id),ti(ti),l(l),r(r),k(k){}}q[N],t[N];int sum[N];void add(int x,int v) { for(int i=x;i<=n;i+=(i&(-i))) sum[i]+=v;}int qry(int x) { int res=0; for(int i=x;i;i-=(i&(-i))) res+=sum[i]; return res;}void cdq(int el,int er,int l,int r,int ql,int qr) { if(el>er||ql>qr) return; if(el==er) { for(int i=ql;i<=qr;i++) ans[q[i].id]=el; return; } int mid=((el+er)>>1); if((el+er)&1) mid++; int ll=l-1,rr=r+1,lx=ql-1,rx=qr+1,now=ql; for(int i=l;i<=r+1;i++) { while(now<=qr&&(i==r+1||q[now].ti =q[now].k) t[--rx]=q[now]; else { q[now].k-=dd; t[++lx]=q[now]; } now++; } if(i==r+1) break; if(cg[i].v>=mid) { tp[--rr]=cg[i]; add(cg[i].pos,cg[i].f); } else tp[++ll]=cg[i]; } int tr=rr,trr=rx; for(int i=rr;i<=r;i++) add(tp[i].pos,-tp[i].f); for(int i=l;i<=ll;i++) cg[i]=tp[i]; for(int i=r;i>ll;i--) cg[i]=tp[tr++]; for(int i=ql;i<=lx;i++) q[i]=t[i]; for(int i=qr;i>lx;i--) q[i]=t[trr++]; cdq(el,mid-1,l,ll,ql,lx); cdq(mid,er,rr,r,rx,qr); } int main() { while(scanf("%d",&n)==1) { int el=1e9,er=0; for(int i=1;i<=n;i++) { read(v[i]); el=min(el,v[i]); er=max(er,v[i]); cg[i]=node(i,i,v[i],1); } read(m); cq=0; for(int i=1;i<=m;i++) { int o,x,y,k; read(o); read(x); read(y); if(o==1) { cg[++n]=node(n+i,x,v[x],-1); cg[++n]=node(n+i,x,y,1); v[x]=y; el=min(el,y); er=max(er,y); } else { read(k); q[++cq]=qs(cq,n+i,x,y,y-x+1-k+1); } } cdq(el,er,1,n,1,cq); for(int i=1;i<=cq;i++) printf("%d\n",ans[i]); } return 0;}/*57 1 9 9 5 12 3 3 1*/