bzoj千题计划258:bzoj3123: [Sdoi2013]森林

http://www.lydsy.com/JudgeOnline/problem.php?id=3123

 

启发式合并主席树

 

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>

using namespace std;

#define N 80001

int n,testcase,m,T;
int val[N];
int front[N],to[N<<1],nxt[N<<1],tot;

int has[N],all;

int fa[N][17],dep[N],lim;

int F[N],siz[N];

int id,root[N];
    
struct node
{
    int lc,rc,cnt;
}tr[N*200];

void read(int &x)
{
    x=0; char c=getchar();
    while(!isdigit(c)) c=getchar();
    while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }
}

void add(int u,int v)
{
    to[++tot]=v; nxt[tot]=front[u]; front[u]=tot;
    to[++tot]=u; nxt[tot]=front[v]; front[v]=tot;
}

int find(int i) { return F[i]==i ? i : F[i]=find(F[i]); }

void unionn(int u,int v)
{
    u=find(u); v=find(v);
    siz[u]+=siz[v];
    F[v]=u;
}

void init()
{
    read(testcase);
    read(n); read(m); read(T);
    lim=log(n)/log(2);
    for(int i=1;i<=n;++i) 
    {
        read(val[i]);
        F[i]=i;
        siz[i]=1;
    }
    int u,v;
    for(int i=1;i<=m;++i)
    {
        read(u); read(v);
        add(u,v);
        unionn(u,v);
    }
}    
void insert(int &x,int y,int l,int r,int pos)
{
    if(!x) x=++id;
    tr[x].cnt=tr[y].cnt+1;
    if(l==r) return;
    int mid=l+r>>1;
    if(pos<=mid) 
    {
        tr[x].rc=tr[y].rc;
        insert(tr[x].lc,tr[y].lc,l,mid,pos);
    }
    else
    {
        tr[x].lc=tr[y].lc;
        insert(tr[x].rc,tr[y].rc,mid+1,r,pos);
    }
}

int query(int u,int v,int lca,int flca,int l,int r,int k)
{
    if(l==r) return l;
    int mid=l+r>>1,tmp=tr[tr[u].lc].cnt+tr[tr[v].lc].cnt-tr[tr[lca].lc].cnt-tr[tr[flca].lc].cnt;
    if(k<=tmp) return query(tr[u].lc,tr[v].lc,tr[lca].lc,tr[flca].lc,l,mid,k);
               return query(tr[u].rc,tr[v].rc,tr[lca].rc,tr[flca].rc,mid+1,r,k-tmp);
}
    
void discrete()
{
    for(int i=1;i<=n;++i) has[i]=val[i];
    sort(has+1,has+n+1);
    all=unique(has+1,has+n+1)-has-1;
    for(int i=1;i<=n;++i) val[i]=lower_bound(has+1,has+all+1,val[i])-has;
}    

void dfs(int x)
{
    dep[x]=dep[fa[x][0]]+1;
    insert(root[x],root[fa[x][0]],1,all,val[x]);
    for(int i=1;i<=lim;++i) fa[x][i]=fa[fa[x][i-1]][i-1];
    for(int i=front[x];i;i=nxt[i])
        if(to[i]!=fa[x][0])
        {
            fa[to[i]][0]=x;
            dfs(to[i]);
        }
}

int get_lca(int u,int v)
{
    if(dep[u]<dep[v]) swap(u,v);
    int x=dep[u]-dep[v];
    for(int i=lim;i>=0;--i)
        if(x&(1<<i)) u=fa[u][i];
    if(u==v) return u;
    for(int i=lim;i>=0;--i)
        if(fa[u][i]!=fa[v][i]) u=fa[u][i],v=fa[v][i];
    return fa[u][0];
}

void solve()
{
    for(int i=1;i<=n;++i) 
        if(!fa[i][0]) dfs(i);
    char ch[3];
    int u,v,k,last=0;
    int lca,fu,fv;
    while(T--)
    {
        scanf("%s",ch);
        if(ch[0]=='Q')
        {    
            read(u); read(v); read(k); 
            u^=last; v^=last; k^=last;
            lca=get_lca(u,v);
            last=has[query(root[u],root[v],root[lca],root[fa[lca][0]],1,all,k)];
            printf("%d\n",last);
        }
        else
        {
            read(u); read(v); 
            u^=last; v^=last;
            fu=find(u); fv=find(v);
            if(siz[fu]<siz[fv]) swap(fu,fv);
            unionn(u,v);
            add(u,v);
            fa[v][0]=u;
            dfs(v);
        }
    }
}

int main()
{
    init();
    discrete();
    solve();
}

 

posted @ 2018-03-06 16:00  TRTTG  阅读(291)  评论(0编辑  收藏  举报