P3224 [HNOI2012]永无乡
事实证明,省选题数据精心造水。我写的那个代码,漏洞多多的,对拍WAON1,AC绿绿的。
这题是一道被出烂了的集合合并,咋做都可以,不过我们闲的写一个splay启发式合并,有个结论,splay按照中序遍历合并,合并一次是均摊\(O(1)\),总共\(nlog\)。
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
#define forg(i,x) for(int i=first[x];i;i=nxt[i])
#define uu unsigned
#define fi first
#define se second
#define od(x) ((x)&1)
#define ev(x) (od(x)^1)
#define mi2(x) (1<<(x))
#define scanf a1234=scanf
#define fre(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout)
int a1234;
char buf[1<<18],*bufs=buf,*buft=buf;
inline int gc(){
return bufs==buft&&(buft=(bufs=buf)+fread(buf,1,1<<18,stdin)),bufs==buft?-1:*bufs++;
}
inline void xxx(){for(;;);}
const int mxn=1e5+3;
int n,m,q,w[mxn];
class unio{
public:
int fa[mxn],siz[mxn];
inline void init(){
for(int i=1;i<=n;++i)fa[i]=i,siz[i]=1;
}
inline int find(int x){
while(x!=fa[x])x=fa[x]=fa[fa[x]];
return x;
}
inline void merge(int x,int y){
x=find(x),y=find(y);fa[x]=y,siz[y]+=siz[x];
}
}us;
#define lch ch[0]
#define rch ch[1]
struct node{
node*ch[2],*prt;
int val,siz,xh;
inline void up(){siz=lch->siz+rch->siz+1;}
}*nil,ap[mxn];
class PSL{
public:
node*po[mxn],*rt[mxn];
inline void init(){
nil=&ap[0];
nil->lch=nil->rch=nil->prt=nil;
nil->siz=0;
for(int i=1;i<=n;++i)po[i]=newd(i,nil);
memcpy(rt,po,sizeof(po));
}
inline node*newd(int xx,node*f){
node*p=&ap[xx];
p->lch=p->rch=nil,p->prt=f,p->val=w[xx],p->xh=xx,p->siz=1;
return p;
}
#define root(x) rt[us.find(x)]
inline int son(node*x){return x==x->prt->rch;}
inline void conn(node*x,node*y,int k){x->prt=y,y->ch[k]=x;}
inline void rotate(node*x){
node*f=x->prt,*g=f->prt,*&r=root(f->xh);
int k=son(x),kk=son(f);
conn(x->ch[k^1],f,k),conn(f,x,k^1);
if(g==nil)r=x,r->prt=nil;else conn(x,g,kk);
f->up(),x->up();
}
inline void splay(node*x,node*y=nil){
while(x->prt!=y){
node*f=x->prt;
if(f->prt==y)return rotate(x);
if(son(x)^son(f))rotate(x),rotate(x);
else rotate(f),rotate(x);
}
}
inline void merge(int x,int y){
if(us.siz[x]>us.siz[y])swap(x,y);
node*r=root(x);us.merge(x,y);
dfs(r,y);
}
inline void dfs(node*x,int y){
if(x->lch!=nil)dfs(x->lch,y),x->lch=nil;
node*kk=x->rch;
x->rch=nil,insert(x,y);
if(kk!=nil)dfs(kk,y);
}
inline void insert(node*x,int y){
node*p=root(y);
while(1){
++p->siz;
node*&nxt=p->ch[p->val<x->val];
if(nxt==nil)return nxt=x,nxt->prt=p,splay(nxt);
p=nxt;
}
}
inline int kth(int d,int x){
node*p=root(d);
while(1){
int num=p->lch->siz;
if(x==num+1)return splay(p),p->xh;
if(x<=num)p=p->lch;
else p=p->rch,x-=num+1;
}
}
}sp;
#undef lch
#undef rch
#undef root
int main(){
scanf("%d%d",&n,&m);for(int i=1;i<=n;++i)scanf("%d",w+i);
us.init(),sp.init();
for(int i=1,u,v;i<=m;++i){scanf("%d%d",&u,&v),u=us.find(u),v=us.find(v);if(u==v)continue;sp.merge(u,v);}
scanf("%d",&q);
while(q--){
char o[3];int x,y;scanf("%s%d%d",o,&x,&y);
if(o[0]=='Q'){
x=us.find(x);
if(us.siz[x]<y){puts("-1");continue;}
printf("%d\n",sp.kth(x,y));
}else if(o[0]=='B'){
x=us.find(x),y=us.find(y);
if(x!=y)sp.merge(x,y);
}
}
return 0;
}
//对拍 这数据略有些不好造
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
#define forg(i,x) for(int i=first[x];i;i=nxt[i])
#define uu unsigned
#define fi first
#define se second
#define ran() ((unsigned)rand())
#define lam(z,k) [&](const z &a,const z &b){ return k; }
#define od(x) ((x)&1)
#define ev(x) (od(x)^1)
#define scanf a1234=scanf
#define system a1234=system
#define fp fprintf
int a1234;
inline void xxx(){for(;;);}
inline int rd(int l,int r){return rand()%(r-l+1)+l;}
inline int rd1(int l,int r){--r;return rand()%(r-l+1)+l;}
FILE* fo;
const int mxn=1e5+3;
int n;
typedef vector<int>::iterator vit;
class unio{
public:
int fa[mxn],siz[mxn],cnt;
vector<int>cx;
inline void init(){
cnt=n;cx=vector<int>();
for(int i=1;i<=n;++i)fa[i]=i,siz[i]=1,cx.push_back(i);
}
inline int find(int x){
while(x!=fa[x])x=fa[x]=fa[fa[x]];
return x;
}
inline void merge(int x,int y){
x=find(x),y=find(y);fa[x]=y,siz[y]+=siz[x];
--cnt,er(x);
}
inline void er(int x){
cx.erase(lower_bound(cx.begin(),cx.end(),x));
}
inline int getan(int x){
er(x);
int res=cx[rd1(0,cx.size())];
cx.insert(lower_bound(cx.begin(),cx.end(),x),x);
return res;
}
}us;
int w[mxn];
inline void maked(){
fo=fopen("te.in","w");
n=rd(1,10000);
us.init();
fp(fo,"%d 0\n",n);
for(int i=1;i<=n;++i)w[i]=i;
random_shuffle(w+1,w+n+1);
for(int i=1;i<=n;++i)fp(fo,"%d ",w[i]);
fp(fo,"\n");
int q=rd(1,10000);fp(fo,"%d\n",q);
for(int i=1;i<=q;++i){
if(us.cnt>1&&rand()%3){
int xx=rd(1,n),x=us.find(xx),y=us.getan(x);
fp(fo,"B %d %d\n",xx,y);
us.merge(x,y);
continue;
}
int x=rd(1,n),y=rd(1,us.siz[us.find(x)]);
fp(fo,"Q %d %d\n",x,y);
}
puts("ok");
fclose(fo);
}
inline int work(){
maked();
system("./a <te.in >1.ans");
system("./b <te.in >2.ans");
return system("diff 1.ans 2.ans -b -B -q");
}
int main(){
srand((uu)time(0));
// maked();return system("cat te.in"),3;
system("g++ ac.cpp -O2 -Wall -o a");
system("g++ yx.cpp -O2 -Wall -o b");
int cases=0;
for(;;){printf("%d\n",++cases);if(work())return 3;if(cases==1000)return 0;}
return 0;
}