[Solution]CF911G
题目描述
题目传送门
思路简述
简单题。观察到
每次操作就相当于将第
这里写的是 FHQ treap(为什么题解区没人写平衡树合并 qwq,感觉平衡树比线段树更简单更好写一点啊)。
启发式合并实现的好好像是跟线段树合并一个复杂度的。
空间复杂度仅是 快来写 FHQ treap 啊。
丑陋の代码
#include <bits/stdc++.h>
#define GC c=getchar()
#define IG isdigit(c)
#define rep(i,l,r) for(int i(l),_##i(r);i<=_##i;++i)
#define per(i,r,l) for(int i(r),_##i(l);i>=_##i;--i)
const int SZ(1<<23);
unsigned char buf[SZ],*s,*t;
#define getchar() (s==t&&(t=buf+fread(s=buf,1,SZ,stdin)),s==t?EOF:*s++)
template<class T=int>T frd(T x=0,char GC,bool f=1)
{
for(;!IG;GC)f=c!='-';for(;IG;GC)x=x*10+(c^48);return f?x:-x;
}
using namespace std;
const int V(100),N(2e5+5);
int n,q,root[V+5],a[N+5];
mt19937 rnd(114514);
struct node {int ls,rs,rk; node() {ls=rs=0,rk=rnd();} }nd[N+5];
void split(int &x,int &y,int rt,int k)
{
if(!rt) return (void)(x=y=0);
if(rt<=k) x=rt,split(nd[x].rs,y,nd[x].rs,k);
else y=rt,split(x,nd[y].ls,nd[y].ls,k);
}
int merge(int x,int y)
{
if(!x||!y) return x+y; if(nd[x].rk>nd[y].rk) swap(x,y); int t1,t2;
split(t1,t2,y,x),nd[x].ls=merge(nd[x].ls,t1),nd[x].rs=merge(nd[x].rs,t2);
return x;
}
void put(int rt,int val)
{
if(rt) a[rt]=val,put(nd[rt].ls,val),put(nd[rt].rs,val);
}
signed main()
{
n=frd();
rep(i,1,n) {int a(frd());root[a]=merge(root[a],i);}
rep(q,1,frd())
{
int l(frd()),r(frd()),x(frd()),y(frd()),t1,t2,t3;
split(t1,t2,root[x],l-1),split(t2,t3,t2,r);
root[x]=merge(t1,t3),root[y]=merge(root[y],t2);
}
rep(i,1,100) put(root[i],i);
rep(i,1,n) printf("%d ",a[i]);
return 0;
}
在我调完代码准备交的时候一不小心把局部的