SDOI2013 森林

题目链接:戳我

呜呜呜又被dreagonm嘲讽了,但是我真的不会写数据结构啊QAQ

链上求第K大+启发式合并

(以下是重构第三遍的代码QAQ)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define MAXN 100010
using namespace std;
int n,m,lastans,tt,sum,tot,T,q;
int f[MAXN],siz[MAXN],p[MAXN][19];
int fa[MAXN],dep[MAXN],rt[MAXN],S[MAXN],a[MAXN],head[MAXN];
struct Edge{int nxt,to;}edge[MAXN<<1];
struct Node{int ls,rs,v;}t[MAXN<<9];
inline void add(int from,int to){edge[++tt].nxt=head[from],edge[tt].to=to,head[from]=tt;}
inline void update(int &x,int f,int l,int r,int pos)
{
    x=++tot;
    t[x]=t[f],t[x].v++;
    if(l==r) return;
    int mid=(l+r)>>1;
    if(pos<=mid) update(t[x].ls,t[f].ls,l,mid,pos);
    else update(t[x].rs,t[f].rs,mid+1,r,pos);
}
inline int query(int x,int y,int lca1,int lca2,int l,int r,int k)
{
    if(l==r) return l;
    int cur=t[t[x].ls].v+t[t[y].ls].v-t[t[lca1].ls].v-t[t[lca2].ls].v;
    int mid=(l+r)>>1;
    if(k<=cur) return query(t[x].ls,t[y].ls,t[lca1].ls,t[lca2].ls,l,mid,k);
    else return query(t[x].rs,t[y].rs,t[lca1].rs,t[lca2].rs,mid+1,r,k-cur);
}
inline int find(int x){return x==f[x]?x:f[x]=find(f[x]);}
inline void merge(int x,int y)
{
    int xx=find(x),yy=find(y);
    f[xx]=yy;
    siz[yy]+=siz[xx],siz[xx]=0;
}
inline int get_lca(int x,int y)
{
    if(dep[x]<dep[y]) swap(x,y);
    int cur=dep[x]-dep[y];
    for(int i=17;i>=0;i--)
        if(cur&(1<<i))
            x=p[x][i];
    if(x==y) return x;
    for(int i=17;i>=0;i--)
        if(p[x][i]!=p[y][i])
            x=p[x][i],y=p[y][i];
    return fa[x];
}
inline void dfs(int x,int pre)
{
    fa[x]=p[x][0]=pre;
    dep[x]=dep[pre]+1;
    update(rt[x],rt[pre],1,sum,a[x]);
    for(int i=1;i<=17;i++)
        p[x][i]=p[p[x][i-1]][i-1];
    for(int i=head[x];i;i=edge[i].nxt)
    {
        int v=edge[i].to;
        if(v==pre) continue;
        dfs(v,x);
    }
}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("ce.in","r",stdin);
    #endif
    scanf("%d",&T);
    memset(head,0,sizeof(head));
    tt=0;
    scanf("%d%d%d",&n,&m,&q);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]),siz[i]=1;
    memcpy(S,a,sizeof(a));
    sort(&S[1],&S[n+1]);
    sum=unique(&S[1],&S[n+1])-S-1;
    for(int i=1;i<=n;i++) a[i]=lower_bound(&S[1],&S[sum+1],a[i])-S;
    for(int i=1;i<=m;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        add(x,y),add(y,x);
        if(siz[find(x)]>siz[find(y)]) merge(y,x);
        else merge(x,y);
    }
    for(int i=1;i<=n;i++)
    {
        if(!rt[i])
            dfs(i,0);
    }
    lastans=0;
    for(int i=1;i<=q;i++)
    {
        char s[10];
        int x,y,k;
        scanf("%s",s);
        if(s[0]=='Q')
        {
            scanf("%d%d%d",&x,&y,&k);
            x^=lastans,y^=lastans,k^=lastans;
            int lca=get_lca(x,y);
            printf("%d\n",lastans=S[query(rt[x],rt[y],rt[lca],rt[fa[lca]],1,sum,k)]);
        }
        else 
        {
            scanf("%d%d",&x,&y);
            x^=lastans,y^=lastans;
            if(siz[find(x)]>siz[find(y)]) swap(x,y);
            merge(x,y);
            dfs(x,y);
            add(x,y),add(y,x);
        }
    }
    return 0;
}
posted @ 2019-05-03 18:46  风浔凌  阅读(142)  评论(0编辑  收藏  举报