树套树-线段树套平衡树

匿名 (未验证) 提交于 2019-12-02 23:55:01
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<vector> #include<cmath> #include<map> #include<bitset> #pragma GCC optimize(2) #define rep(i,a,b) for(int i=(a);i<=(b);++i) #define dwn(i,a,b) for(int i=(a);i>=(b);--i) using namespace std; typedef long long ll; const int N=6000000,inf=2147483647; int n,m,maxn,a[N+10]; int tot,rt[N+10],sz[N+10],rec[N+10],v[N+10],fa[N+10],ch[N+10][2]; inline int read() {     int x=0,f=1;     char ch=getchar();     while(ch<'0'||ch>'9')     {         if(ch=='-') f=-1;         ch=getchar();     }     while(ch>='0'&&ch<='9')     {         x=(x<<3)+(x<<1)+(ch^48);         ch=getchar();     }     return x*f; } //----------------------Splay-------------------------- inline int ident(int x){return ch[fa[x]][0]==x?0:1;} inline void splay_clear(int x){fa[x]=ch[x][0]=ch[x][1]=sz[x]=rec[x]=v[x]=0;} inline void splay_pushup(int x){sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+rec[x];} inline void rotate(int x) {     int Y=fa[x],R=fa[Y],Yson=ident(x),Rson=ident(Y);     if(R)ch[R][Rson]=x;     if(ch[x][Yson^1]) fa[ch[x][Yson^1]]=Y;     ch[Y][Yson]=ch[x][Yson^1];     ch[x][Yson^1]=Y;     fa[Y]=x;     fa[x]=R;     splay_pushup(Y),splay_pushup(x); } inline void splay(int &rt,int x,int to) {     to=fa[to];     while(fa[x]!=to)     {         int y=fa[x];         if(fa[y]==to) rotate(x);         else if(ident(x)==ident(y)) rotate(y),rotate(x);         else rotate(x),rotate(x);     }     if(!to) rt=x; } inline void splay_insert(int &rt,int d) {     if(!rt)     {         rt=++tot;         v[rt]=d;         sz[rt]=rec[rt]=1;         fa[rt]=ch[rt][0]=ch[rt][1]=0;         return;     }     int x=rt;     while(1)     {         sz[x]++;         if(v[x]==d){rec[x]++;splay(rt,x,rt);return;}         int nxt=d<v[x]?0:1;         if(!ch[x][nxt])         {             ch[x][nxt]=++tot;             v[tot]=d;             sz[tot]=rec[tot]=1;             fa[tot]=x;             ch[tot][0]=ch[tot][1]=0;             splay(rt,tot,rt);             return;         }         x=ch[x][nxt];     } } inline int splay_rk(int &rt,int d) {     int x=rt,ans=0;     while(1)     {         if(!x){return ans;}         if(v[x]==d){ans+=sz[ch[x][0]];splay(rt,x,rt);return ans;}         int nxt=d<v[x]?0:1;         if(nxt==1) ans+=sz[ch[x][0]]+rec[x];         x=ch[x][nxt];     } } inline int splay_find(int &rt,int d) {     int x=rt;     while(1)     {         if(!x) return 0;         if(v[x]==d){splay(rt,x,rt);return x;}         int nxt=d<v[x]?0:1;         x=ch[x][nxt];     } } inline void splay_del(int &rt,int d) {     int x=splay_find(rt,d);     if(!x) return;     if(rec[x]>=2){rec[x]--,sz[x]--;return;}     if(!ch[x][0]&&!ch[x][1]){rt=0;return;}     if(!ch[x][0]){rt=ch[x][1];fa[rt]=0;return;}     if(!ch[x][1]){rt=ch[x][0];fa[rt]=0;return;}     int left=ch[x][0];     while(ch[left][1]) left=ch[left][1];     splay(rt,left,ch[x][0]);     fa[ch[x][1]]=left;     ch[left][1]=ch[x][1];     fa[left]=0;     rt=left;     splay_pushup(left); } inline int splay_lower(int &rt,int d) {     int x=rt,ans=-inf;     while(x)     {         if(v[x]<d) ans=max(ans,v[x]);         int nxt=d<=v[x]?0:1;         x=ch[x][nxt];     }     return ans; } inline int splay_upper(int &rt,int d) {     int x=rt,ans=inf;     while(x)     {         if(v[x]>d) ans=min(ans,v[x]);         int nxt=d<v[x]?0:1;         x=ch[x][nxt];     }     return ans; } //----------------------Seg_Tree-------------------------- void seg_insert(int k,int l,int r,int x,int d) {     splay_insert(rt[k],d);     if(l==r) return;     int mid=(l+r)>>1;     if(x<=mid) seg_insert(k<<1,l,mid,x,d);     else seg_insert(k<<1|1,mid+1,r,x,d); } int seg_rk(int k,int l,int r,int ql,int qr,int d) {      if(ql<=l&&r<=qr){return splay_rk(rt[k],d);}     int ans=0,mid=(l+r)>>1;     if(ql<=mid) ans+=seg_rk(k<<1,l,mid,ql,qr,d);     if(qr>=mid+1) ans+=seg_rk(k<<1|1,mid+1,r,ql,qr,d);     return ans; } void seg_change(int k,int l,int r,int x,int d) {     splay_del(rt[k],a[x]),splay_insert(rt[k],d);     if(l==r){a[x]=d;return;}     int mid=(l+r)>>1;     if(x<=mid) seg_change(k<<1,l,mid,x,d);     else seg_change(k<<1|1,mid+1,r,x,d); } int seg_lower(int k,int l,int r,int ql,int qr,int d) {     if(ql<=l&&r<=qr) return splay_lower(rt[k],d);     int ans=-inf,mid=(l+r)>>1;     if(ql<=mid) ans=max(ans,seg_lower(k<<1,l,mid,ql,qr,d));     if(qr>=mid+1) ans=max(ans,seg_lower(k<<1|1,mid+1,r,ql,qr,d));     return ans; } int seg_upper(int k,int l,int r,int ql,int qr,int d) {     if(ql<=l&&r<=qr) return splay_upper(rt[k],d);     int ans=inf,mid=(l+r)>>1;     if(ql<=mid) ans=min(ans,seg_upper(k<<1,l,mid,ql,qr,d));     if(qr>=mid+1) ans=min(ans,seg_upper(k<<1|1,mid+1,r,ql,qr,d));     return ans; } inline int seg_kth(int ql,int qr,int k) {     int l=0,r=maxn+1,ans;     while(l<=r)     {         int mid=(l+r)>>1;         if(seg_rk(1,1,n,ql,qr,mid)+1<=k) ans=mid,l=mid+1;         else r=mid-1;     }     return ans; } int main() {     n=read(),m=read();     rep(i,1,n) a[i]=read(),seg_insert(1,1,n,i,a[i]),maxn=max(maxn,a[i]);     rep(i,1,m)     {         int opt=read(),x=read(),y=read(),k;         if(opt==1) k=read(),printf("%d\n",seg_rk(1,1,n,x,y,k)+1);         if(opt==2) k=read(),printf("%d\n",seg_kth(x,y,k));         if(opt==3) maxn=max(maxn,y),seg_change(1,1,n,x,y);         if(opt==4) k=read(),printf("%d\n",seg_lower(1,1,n,x,y,k));         if(opt==5) k=read(),printf("%d\n",seg_upper(1,1,n,x,y,k));     }     return 0; }
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!