用平衡树模拟这个过程,每个点维护它代表的小球的颜色和个数。
操作一新建一个颜色为 x,个数为 y 的结点。
操作二是基本的平衡树删除操作。
操作三,把第 u 个桶的平衡树打上翻转标记,再合并到第 v 个桶的平衡树上。
Code:
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <cmath> #define Rint register int #define INF 0x3f3f3f3f using namespace std; typedef long long lxl; const int maxn=3e5+5; template <typename T> inline void read(T &x) { x=0;T f=1;char ch=getchar(); while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();} while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} x*=f; } int n,m; namespace Treap { int tot,pool[maxn],top; int ch[maxn][2]; lxl siz[maxn],cnt[maxn]; int val[maxn],rnd[maxn]; bool rev[maxn]; inline int new_node() { int p=top?pool[top--]:++tot; ch[p][0]=ch[p][1]=0; siz[p]=cnt[p]=0; val[p]=rnd[p]=0; rev[p]=false; return p; } inline void reverse(int p) { swap(ch[p][0],ch[p][1]); rev[p]^=1; } inline void push_down(int p) { if(!rev[p]) return; reverse(ch[p][0]); reverse(ch[p][1]); rev[p]=0; } inline void update(int p) { siz[p]=siz[ch[p][0]]+siz[ch[p][1]]+cnt[p]; } void split_rnk(int p,int k,int &x,int &y,int &z) { if(!p) return x=y=z=0,void(); push_down(p); if(siz[ch[p][0]]>=k) { z=p; split_rnk(ch[p][0],k,x,y,ch[p][0]); } else if(siz[ch[p][0]]+cnt[p]<k) { x=p; split_rnk(ch[p][1],k-siz[ch[p][0]]-cnt[p],ch[p][1],y,z); } else { x=ch[p][0],y=p,z=ch[p][1]; ch[p][0]=ch[p][1]=0; } update(p); } int merge(int a,int b) { if(!a||!b) return a|b; push_down(a),push_down(b); if(rnd[a]<rnd[b]) { ch[a][1]=merge(ch[a][1],b); update(a); return a; } else { ch[b][0]=merge(a,ch[b][0]); update(b); return b; } } inline int new_node(int s,int c) { if(!s) return 0; int p=new_node(); siz[p]=cnt[p]=s; val[p]=c; rnd[p]=rand(); return p; } inline void erase(int &p) { if(!p) return; erase(ch[p][0]); erase(ch[p][1]); pool[++top]=p; p=0; } // inline void print(int p) // { // if(!p) return; // push_down(p); // print(ch[p][0]); // for(int i=1;i<=cnt[p];++i) // printf("%d ",val[p]); // print(ch[p][1]); // } } int rt[maxn]; int main() { #ifndef ONLINE_JUDGE freopen("B.in","r",stdin); freopen("B.out","w",stdout); #endif read(n),read(m); char opt[5]; int x,y,z; while(m--) { scanf(" %s",opt); read(x),read(y); if(opt[2]=='s') { read(z); rt[z]=Treap::merge(Treap::new_node(x,y),rt[z]); } else if(opt[2]=='p') { int a,b,c; Treap::split_rnk(rt[y],x,a,b,c); rt[y]=Treap::merge(Treap::new_node(Treap::siz[a]+Treap::cnt[b]-x,Treap::val[b]),c); printf("%d\n",Treap::val[b]); Treap::erase(a); Treap::erase(b); } else { Treap::reverse(rt[x]); rt[y]=Treap::merge(rt[x],rt[y]); rt[x]=0; } // puts("---"); // for(int i=1;i<=n;++i) // Treap::print(rt[i]),puts(""); // puts("---"); } return 0; }