BZOJ 3196 二逼平衡树 ——树套树
【题目分析】
全靠运气,卡空间。
xjb试几次就过了。
【代码】
#include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define maxn 200005 #define mlog 16 #define inf 0x3f3f3f3f #define maxm 4000005 #define F(i,j,k) for (int i=j;i<=k;++i) int ch[maxm][2],fa[maxm],siz[maxm],v[maxm],num[maxm],n,m,rt[maxn*5],a[maxn]; int L,R,X,C,tot,Pre,Nxt,opt,ans,k,aim; void update(int k) {siz[k]=siz[ch[k][0]]+siz[ch[k][1]]+num[k];} int ins(int &k,int fat) { if (!k){k=++tot;num[k]=siz[k]=1;v[k]=C;fa[k]=fat;ch[k][0]=ch[k][1]=0;return k;} siz[k]++; if (C==v[k]) {num[k]++;return k;} else if (C<v[k]) return ins(ch[k][0],k); else return ins(ch[k][1],k); } void rot(int x,int &k) { int y=fa[x],z=fa[y],l=0,r; if (ch[y][1]==x) l=1; r=l^1; if (y==k) k=x; else { if (ch[z][0]==y) ch[z][0]=x; else ch[z][1]=x; } fa[x]=z; fa[y]=x; fa[ch[x][r]]=y; ch[y][l]=ch[x][r]; ch[x][r]=y; update(y); update(x); } void splay(int x,int &k) { while (x!=k) { int y=fa[x],z=fa[y]; if (y!=k) { if (ch[z][0]==y^ch[y][0]==x) rot(x,k); rot(y,k); } rot(x,k); } } void add(int o,int l,int r) { int mid=l+r>>1; splay(ins(rt[o],0),rt[o]); if (l==r) return; if (X<=mid) add(o<<1,l,mid); else add(o<<1|1,mid+1,r); } void qrk(int k) { if (!k) return; if (v[k]<C) {ans+=siz[ch[k][0]]+num[k];return qrk(ch[k][1]);} if (v[k]==C) {ans+=siz[ch[k][0]];return;} return qrk(ch[k][0]); } void queryrk(int o,int l,int r) { if (L<=l&&r<=R){qrk(rt[o]);return;} int mid=l+r>>1; if (L<=mid) queryrk(o<<1,l,mid); if (R>mid) queryrk(o<<1|1,mid+1,r); } void qpr(int k) { if (!k) return; if (v[k]>=C) return qpr(ch[k][0]); else{Pre=max(Pre,v[k]); return qpr(ch[k][1]);} } void querypr(int o,int l,int r) { if (L<=l&&r<=R){qpr(rt[o]);return;} int mid=l+r>>1; if (L<=mid) querypr(o<<1,l,mid); if (R>mid) querypr(o<<1|1,mid+1,r); } void qnt(int k) { if (!k) return; if (v[k]<=C) return qnt(ch[k][1]); else{Nxt=min(Nxt,v[k]); return qnt(ch[k][0]);} } void querynt(int o,int l,int r) { if (L<=l&&r<=R){qnt(rt[o]);return;} int mid=l+r>>1; if (L<=mid) querynt(o<<1,l,mid); if (R>mid) querynt(o<<1|1,mid+1,r); } void del(int &k) { if (v[k]==C) { if (num[k]>1) { num[k]--; siz[k]--; splay(k,rt[aim]); return ; } else { if (ch[k][0]*ch[k][1]==0) { if ((!ch[k][0])&&(!ch[k][1])) {k=0;return;} if (!ch[k][0]) fa[ch[k][1]]=fa[k]; else fa[ch[k][0]]=fa[k]; k=ch[k][0]+ch[k][1]; return ; } else { int tmp=rand()%2; rot(ch[k][tmp],k); del(k); return ; } } } siz[k]--; if (v[k]<C) del(ch[k][1]); else del(ch[k][0]); } void dec(int o,int l,int r) { int mid=(l+r)/2;aim=o; del(rt[o]); if (l==r) return ; if (X<=mid) dec(o<<1,l,mid); else dec(o<<1|1,mid+1,r); } int main() { int l,r; // freopen("in.txt","r",stdin); scanf("%d%d",&n,&m); F(i,1,n) { scanf("%d",&a[i]); X=i; C=a[i]; add(1,1,n); } F(i,1,m) { scanf("%d",&opt); switch(opt) { case 1: ans=0; scanf("%d%d%d",&L,&R,&C); queryrk(1,1,n); printf("%d\n",ans+1); break; case 2: scanf("%d%d%d",&L,&R,&k); l=-inf; r=inf; while (l<r) { int mid=(l+r)/2+1; C=mid; ans=0; queryrk(1,1,n); if (ans<=k-1) l=mid; else r=mid-1; } printf("%d\n",r); break; case 3: scanf("%d%d",&X,&k); C=a[X]; dec(1,1,n); a[X]=k; C=a[X]; add(1,1,n); break; case 4: Pre=-inf; scanf("%d%d%d",&L,&R,&C); querypr(1,1,n); printf("%d\n",Pre); break; case 5: Nxt=inf; scanf("%d%d%d",&L,&R,&C); querynt(1,1,n); printf("%d\n",Nxt); break; } } }