BZOJ2773(HNOI2012)[永无乡]--Splay启发式合并

【链接】
bzoj2733

【解题报告】

好像是平衡树裸题吧,然后splay启发式合并码掉了。

#include
#include
using namespace std;
const int maxn=100005;
int n,m,Q,w[maxn],c[maxn],fa[maxn];
struct Splay
{
    Splay* son[2];
    int x,s,p;
    Splay (int a=0,int b=0,Splay* t=NULL) {x=a; p=b; s=1; son[0]=son[1]=t;}
    int Cmp1(int k) {if (k==p) return -1; if (kreturn 0; return 1;}
    int Cmp2(int &k) {int t=son[0]->s+1; if (k==t) return -1; if (kreturn 0; k-=t; return 1;}
    void Pushup() {s=son[0]->s+son[1]->s+1;}
}tem[maxn],*Null=tem,*len=Null,*ro[maxn];
inline char nc()
{
    static char buf[100000],*l,*r;
    if (l==r) r=(l=buf)+fread(buf,1,100000,stdin);
    if (l==r) return EOF; return *l++;
}
inline int Read()
{
    int res=0,f=1; char ch=nc(),cc=ch;
    while (ch<'0'||ch>'9') cc=ch,ch=nc();
    if (cc=='-') f=-1;
    while (ch>='0'&&ch<='9') res=res*10+ch-48,ch=nc();
    return res*f;
}
void init_Null() {Null->s=0; Null->son[0]=Null->son[1]=Null;}
void Rotate(Splay* &k,int d)
{
    Splay* t=k->son[d]; k->son[d]=t->son[d^1]; t->son[d^1]=k;
    k->Pushup(); t->Pushup(); k=t;
}
void Splay_Work(Splay* &k,int x)
{
    int d1=k->Cmp1(x);
    if (d1>-1)
    {
        Splay* p=k->son[d1];
        int d2=p->Cmp1(x);
        if (d2>-1)
        {
            Splay_Work(p->son[d2],x);
            if (d1==d2) Rotate(k,d1),Rotate(k,d1); else Rotate(k->son[d1],d2),Rotate(k,d1);
        } else Rotate(k,d1);
    }
}
int Kth(Splay* &k,int x)
{
    int d=k->Cmp2(x);
    if (d<0) return k->x;
     else return Kth(k->son[d],x);
}
int Getfa(int x)
{
    if (x==fa[x]) return x;
    fa[x]=Getfa(fa[x]);
    return fa[x];
}
void Insert(Splay* &k,int x,int p)
{
    if (k==Null) k=new Splay(x,p,Null);
     else Insert(k->son[p>k->p],x,p);
    k->Pushup();
}
void Delete(Splay* k)
{
    if (k==Null) return;
    Delete(k->son[0]); c[++c[0]]=k->x; Delete(k->son[1]);
    delete k;
}
void Merga(int x,int y)
{
    x=Getfa(x); y=Getfa(y);
    if (x==y) return;
    Splay *p1=ro[x],*p2=ro[y];
    if (p1->ss) swap(p1,p2); 
    c[0]=0; Delete(p2);
    for (int i=1; i<=c[0]; i++) Insert(p1,c[i],w[c[i]]),Splay_Work(p1,w[c[i]]);
    ro[fa[x]=y]=p1;
}
int main()
{
    freopen("2733.in","r",stdin);
    freopen("2733.out","w",stdout);
    n=Read(); m=Read(); init_Null();
    for (int i=1,x; i<=n; i++) w[i]=Read(),fa[i]=i,ro[i]=new Splay(i,w[i],Null);
    for (int i=1,x,y; i<=m; i++) x=Read(),y=Read(),Merga(x,y);
    Q=Read();
    while(Q--)
    {
        char ch=nc();
        while (ch!='Q'&&ch!='B') ch=nc();
        int x=Read(),y=Read();
        if (ch=='Q') {int t=Getfa(x); if (ro[t]->sprintf("-1\n"); else {int v=Kth(ro[t],y); Splay_Work(ro[t],w[v]); printf("%d\n",v);}}
         else Merga(x,y);
    }
    return 0;
}

你可能感兴趣的:(BZOJ题解,平衡树,BZOJ题解,By,Greninja,部分常见刷题网站的题解,By,Greninja,平衡树,BZOJ,启发式合并)