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;
}
posted @ 2020-09-27 16:27  yugyppah656  阅读(130)  评论(0编辑  收藏  举报