题解:
看到网上几乎全是树套树,
我就写了个整体二分。
其中操作1,2,3一般整体二分都能做到。
对于前驱,我们只需要在线段树中多维护区间最大值即可;
对于后继……
通通取反后再跑一遍查询前驱即可。
然后迷之卡空间。
最后迷之卡过。
代码:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define N 500050 const int inf = 0x3f3f3f3f; inline int rd() { int f=1,c=0;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){c=10*c+ch-'0';ch=getchar();} return f*c; } int n,m,tot,cnt,qcnt,ans[N],vl[N],mx,to[5*N/2]; struct node { int opt,id; int l,r,k; int num; }p[5*N/2],tmpl[5*N/2],tmpr[5*N/2]; bool nmp(node a,node b) { return a.num<b.num; } struct Pair { int x,id; Pair(){} Pair(int x,int i):x(x),id(i){} }o[5*N/2]; bool cmp(Pair a,Pair b) { return a.x<b.x; } struct segtree { int siz[5*N/2],sum[5*N/2],tag[5*N/2],mx[5*N/2]; bool rec[5*N/2]; void add(int u,int d) { tag[u]+=d; sum[u]+=siz[u]*d; } void rece(int u) { sum[u]=tag[u]=0; mx[u]=-inf; rec[u]=1; } void pushdown(int u) { if(rec[u]) { rece(u<<1); rece(u<<1|1); rec[u]=0; } if(tag[u]) { add(u<<1,tag[u]); add(u<<1|1,tag[u]); tag[u] = 0; } } void update(int u) { mx[u] = max(mx[u<<1],mx[u<<1|1]); sum[u] = sum[u<<1]+sum[u<<1|1]; } void build(int l,int r,int u) { siz[u] = r-l+1; mx[u] = -inf; if(l==r)return ; int mid = (l+r)>>1; build(l,mid,u<<1); build(mid+1,r,u<<1|1); } void insert(int l,int r,int u,int qx,int qd,int d) { if(l==r) { sum[u] += d; if(!sum[u])mx[u]=-inf; else mx[u] = qd; return ; } pushdown(u); int mid = (l+r)>>1; if(qx<=mid)insert(l,mid,u<<1,qx,qd,d); else insert(mid+1,r,u<<1|1,qx,qd,d); update(u); } int q1(int l,int r,int u,int ql,int qr) { if(l==ql&&r==qr)return sum[u]; pushdown(u); int mid = (l+r)>>1; if(qr<=mid)return q1(l,mid,u<<1,ql,qr); else if(ql>mid)return q1(mid+1,r,u<<1|1,ql,qr); else return q1(l,mid,u<<1,ql,mid)+q1(mid+1,r,u<<1|1,mid+1,qr); } int q2(int l,int r,int u,int ql,int qr) { if(l==ql&&r==qr)return mx[u]; pushdown(u); int mid = (l+r)>>1; if(qr<=mid)return q2(l,mid,u<<1,ql,qr); else if(ql>mid)return q2(mid+1,r,u<<1|1,ql,qr); else return max(q2(l,mid,u<<1,ql,mid),q2(mid+1,r,u<<1|1,mid+1,qr)); } }tr; void divi(int l,int r,int beg,int ens) { if(beg>ens)return ; if(l==r) { for(int i=beg;i<=ens;i++) if(p[i].opt==2)ans[p[i].id]=to[l]; return ; } int mid = (l+r)>>1; int lt = 0,rt = 0; bool l1 = 0,r1 = 0; tr.rece(1); for(int i=beg;i<=ens;i++) { if(p[i].opt==0) { if(p[i].k<=mid) { tr.insert(1,n,1,p[i].id,to[p[i].k],1); tmpl[++lt] = p[i]; }else tmpr[++rt] = p[i]; }else if(p[i].opt==1) { if(p[i].k>mid) { ans[p[i].id]+=tr.q1(1,n,1,p[i].l,p[i].r); tmpr[++rt] = p[i];r1=1; }else tmpl[++lt] = p[i],l1=1; }else if(p[i].opt==2) { int now = tr.q1(1,n,1,p[i].l,p[i].r); if(now<p[i].k) { p[i].k-=now; tmpr[++rt] = p[i];r1=1; }else tmpl[++lt] = p[i],l1=1; }else if(p[i].opt==3) { if(p[i].k<=mid) { tr.insert(1,n,1,p[i].id,to[p[i].k],-1); tmpl[++lt] = p[i]; }else tmpr[++rt] = p[i]; }else if(p[i].opt==4) { if(p[i].k>mid) { ans[p[i].id] = max(ans[p[i].id],tr.q2(1,n,1,p[i].l,p[i].r)); tmpr[++rt] = p[i];r1=1; }else tmpl[++lt] = p[i],l1=1; }else tmpr[++rt] = p[i]; } for(int i=beg;i<=beg+lt-1;i++)p[i]=tmpl[i-beg+1]; for(int i=beg+lt;i<=ens;i++)p[i]=tmpr[i-beg-lt+1]; if(l1)divi(l,mid,beg,beg+lt-1); if(r1)divi(mid+1,r,beg+lt,ens); } void dv(int l,int r,int beg,int ens) { if(beg>ens)return ; if(l==r)return ; int mid = (l+r)>>1; int lt = 0,rt = 0,i; bool l1 = 0,r1 = 0; tr.rece(1); for(i=beg;i<=ens;i++) { if(p[i].opt==0) { if(-p[i].k<=mid) { tr.insert(1,n,1,p[i].id,-to[p[i].k],1); tmpl[++lt] = p[i]; }else tmpr[++rt] = p[i]; }else if(p[i].opt==3) { if(-p[i].k<=mid) { tr.insert(1,n,1,p[i].id,-to[p[i].k],-1); tmpl[++lt] = p[i]; }else tmpr[++rt] = p[i]; }else if(p[i].opt==5) { if(-p[i].k>mid) { int tmp = tr.q2(1,n,1,p[i].l,p[i].r); if(tmp!=-inf)ans[p[i].id] = max(ans[p[i].id],tmp); tmpr[++rt] = p[i];r1=1; }else tmpl[++lt] = p[i],l1=1; } } for(i=beg;i<=beg+lt-1;i++)p[i]=tmpl[i-beg+1]; for(i=beg+lt;i<=beg+lt+rt-1;i++)p[i]=tmpr[i-beg-lt+1]; if(l1)dv(l,mid,beg,beg+lt-1); if(r1)dv(mid+1,r,beg+lt,beg+lt+rt-1); } int main() { // freopen("7.in","r",stdin); tot = n = rd(),m = rd(); for(int i=1;i<=n;i++) { vl[i] = rd(); p[i].id = i; o[++cnt] = Pair(vl[i],i); } for(int opt,l,r,k,id,i=1;i<=m;i++) { opt = rd(),tot++;p[tot].opt = opt; if(opt==3)id=rd(),k=rd(); else l=rd(),r=rd(),k=rd(); if(opt==1||opt==4||opt==5)p[tot].l=l,p[tot].r=r,o[++cnt]=Pair(k,tot),p[tot].id=++qcnt; if(opt==2)p[tot].l=l,p[tot].r=r,p[tot].k=k,p[tot].id=++qcnt; if(opt==3) { p[tot].id = id;o[++cnt]=Pair(vl[id],tot); tot++; p[tot].id = id;o[++cnt]=Pair(k,tot); vl[id] = k; } if(opt==1)ans[qcnt]=1; if(opt>=4)ans[qcnt]=-inf; } sort(o+1,o+1+cnt,cmp); for(int las=inf,i=1;i<=cnt;i++) { if(las!=o[i].x) { las = o[i].x; to[++mx] = las; } p[o[i].id].k = mx; } for(int i=1;i<=tot;i++)p[i].num=i; tr.build(1,n,1); divi(1,mx,1,tot); sort(p+1,p+1+tot,nmp); dv(-mx,-1,1,tot); for(int i=1;i<=qcnt;i++) printf("%d ",ans[i]*(ans[i]<0?-1:1)); return 0; }