BZOJ3196:二逼平衡樹
阿新 • • 發佈:2018-12-24
line www del return urn 一個 std nod r+
淺談樹狀數組與線段樹:https://www.cnblogs.com/AKMer/p/9946944.html
淺談\(Splay\):https://www.cnblogs.com/AKMer/p/9979592.html
樹套樹模板題,外層用一個位置線段樹,內層用一個平衡樹即可解決。
查第\(k\)大是誰需要在外面套一個二分。這題比較卡,反正我是勉勉強強跑過去的……
時間復雜度:\(O(nlog^3n)\)
空間復雜度:\(O(nlogn)\)
代碼如下:
#include <cstdio> #include <algorithm> using namespace std; const int maxn=5e4+5,inf=2147483647; int a[maxn]; int n,m,mn=1e9,mx=-1e9; int read() { int x=0,f=1;char ch=getchar(); for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1; for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0'; return x*f; } struct Splay { int tot; int son[maxn*25][2],fa[maxn*25]; int siz[maxn*25],cnt[maxn*25],val[maxn*25]; int newnode(int v) { val[++tot]=v; siz[tot]=cnt[tot]=1; return tot; } int find(int rt,int v) { int u=rt; while(val[u]!=v) { if(val[u]>v) {if(son[u][0])u=son[u][0];else break;} if(val[u]<v) {if(son[u][1])u=son[u][1];else break;} } return u; } int t(int u) { return son[fa[u]][1]==u; } void updata(int u) { siz[u]=siz[son[u][0]]+cnt[u]+siz[son[u][1]]; } void rotate(int u) { int ret=t(u),f=fa[u],s=son[u][ret^1]; son[f][ret]=s;if(s)fa[s]=f;son[u][ret^1]=f; fa[u]=fa[f];if(fa[f])son[fa[f]][t(f)]=u; fa[f]=u;updata(f);updata(u); } void splay(int &rt,int u) { while(fa[u]) { if(fa[fa[u]]) { if(t(fa[u])!=t(u))rotate(u); else rotate(fa[u]); } rotate(u); } rt=u; } void ins(int &rt,int v) { if(!rt) {rt=newnode(v);return;} int u=find(rt,v); if(val[u]==v) {siz[u]++,cnt[u]++,splay(rt,u);return;} fa[newnode(v)]=u;son[u][v>val[u]]=tot;splay(rt,tot); } int get_rk(int &rt,int v) { int u=find(rt,v);splay(rt,u); if(val[u]>=v)return siz[son[u][0]]; return siz[son[u][0]]+cnt[u]; } void del(int &rt,int v) { int u=find(rt,v);splay(rt,u); if(cnt[u]>1) {cnt[u]--,siz[u]--;return;} if(!son[u][0]) {rt=son[u][1],fa[rt]=0;return;} if(!son[u][1]) {rt=son[u][0],fa[rt]=0;return;} int node=son[u][0];while(son[node][1])node=son[node][1]; fa[son[u][0]]=0;splay(rt,node); son[node][1]=son[u][1];fa[son[u][1]]=node; updata(node); } int get_pre(int &rt,int v) { int u=find(rt,v);splay(rt,u); if(val[u]<v)return val[u]; int node=son[u][0]; while(son[node][1])node=son[node][1]; if(node)return val[node]; return -inf; } int get_suc(int &rt,int v) { int u=find(rt,v);splay(rt,u); if(val[u]>v)return val[u]; int node=son[u][1]; while(son[node][0])node=son[node][0]; if(node)return val[node]; return inf; } }S; struct segment_tree { int rt[maxn<<2]; void build(int p,int l,int r) { for(int i=l;i<=r;i++) S.ins(rt[p],a[i]); if(l==r)return; int mid=(l+r)>>1; build(p<<1,l,mid); build(p<<1|1,mid+1,r); } int query_rk(int p,int l,int r,int L,int R,int v) { if(L<=l&&r<=R)return S.get_rk(rt[p],v); int mid=(l+r)>>1,res=0; if(L<=mid)res=query_rk(p<<1,l,mid,L,R,v); if(R>mid)res+=query_rk(p<<1|1,mid+1,r,L,R,v); return res; } void change(int p,int l,int r,int pos,int v_before,int v_after) { S.del(rt[p],v_before);S.ins(rt[p],v_after); if(l==r)return; int mid=(l+r)>>1; if(pos<=mid)change(p<<1,l,mid,pos,v_before,v_after); else change(p<<1|1,mid+1,r,pos,v_before,v_after); } int query_pre(int p,int l,int r,int L,int R,int v) { if(L<=l&&r<=R)return S.get_pre(rt[p],v); int mid=(l+r)>>1,res=-inf; if(L<=mid)res=max(res,query_pre(p<<1,l,mid,L,R,v)); if(R>mid)res=max(res,query_pre(p<<1|1,mid+1,r,L,R,v)); return res; } int query_suc(int p,int l,int r,int L,int R,int v) { if(L<=l&&r<=R)return S.get_suc(rt[p],v); int mid=(l+r)>>1,res=inf; if(L<=mid)res=min(res,query_suc(p<<1,l,mid,L,R,v)); if(R>mid)res=min(res,query_suc(p<<1|1,mid+1,r,L,R,v)); return res; } }T; int main() { n=read(),m=read(); for(int i=1;i<=n;i++) a[i]=read(),mn=min(mn,a[i]),mx=max(mx,a[i]); T.build(1,1,n); for(int i=1;i<=m;i++) { int opt=read(),l,r,pos,k; if(opt==3)pos=read(),k=read(); else l=read(),r=read(),k=read(); if(opt==1)printf("%d\n",T.query_rk(1,1,n,l,r,k)+1); if(opt==2) { int L=mn,R=mx; while(L<R) { int mid=(L+R+1)>>1; int rk=T.query_rk(1,1,n,l,r,mid)+1; if(rk>k)R=mid-1; else L=mid; } printf("%d\n",L); } if(opt==3)T.change(1,1,n,pos,a[pos],k),a[pos]=k,mn=min(mn,k),mx=max(mx,k); if(opt==4)printf("%d\n",T.query_pre(1,1,n,l,r,k)); if(opt==5)printf("%d\n",T.query_suc(1,1,n,l,r,k)); } return 0; }
BZOJ3196:二逼平衡樹