[SDOI2013]森林

这道题是主席树维护树上K大值。需要可持久化线段树启发式合并。
没有link的话就和count on a tree 一样,有link的话就暴力重构size较小的树,时间复杂度....
真的是头铁。。。
树剖求lca维护起来好麻烦啊。。。可能是我的锅
UPD:就是我的锅....启发式合并一直写的是错的...
倍增的话维护lca就很简单了
坑点:T表示的是数据是第几组。。。
树剖写的在bzoj上T了 划掉!是我的启发式合并写的和个智障一样!!!!BZOJ上也A了!

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
const int N=80005;
int T,n,m,q,fa[N],blo,p[N],dep[N],SIZ[N],son[N],top[N],head[N],ecnt,to[N<<1],nxt[N<<1],root[N],cnt,tot,rt[N],ls[80000*500],rs[80000*500],siz[80000*500],LSH,lsh[N],bl[N];
inline int rd(){
    int x=0;char ch=' ';int f=1;
    while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    if(ch=='-')f=-1,ch=getchar();
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    return x*f;
}
void add(int bg,int ed) {
    nxt[++ecnt]=head[bg];
    to[ecnt]=ed;
    head[bg]=ecnt;
}
void update(int &k,int pre,int l,int r,int val) {
    k=++tot;
    ls[k]=ls[pre],rs[k]=rs[pre],siz[k]=siz[pre]+1;
    if(l<r) {
        int mid=l+r>>1;
        if(val<=mid) update(ls[k],ls[pre],l,mid,val);
        else update(rs[k],rs[pre],mid+1,r,val);
    }
}
void build(int &k,int l,int r) {
    k=++tot;
    if(l<r) {
        int mid=l+r>>1;
        build(ls[k],l,mid);
        build(rs[k],mid+1,r);
    }
}
void dfs(int x) {
    SIZ[x]=1;bl[x]=cnt;son[x]=0;
    update(rt[x],rt[fa[x]],1,LSH,p[x]);
    for(int i=head[x]; i; i=nxt[i]) {
        if(fa[x]!=to[i]) {
            fa[to[i]]=x,dep[to[i]]=dep[x]+1,dfs(to[i]),SIZ[x]+=SIZ[to[i]];
            if(SIZ[to[i]]>SIZ[son[x]]) son[x]=to[i];
        }
    }
}
void dfs(int x,int qtop) {
    top[x]=qtop;
    if(!son[x]) return;
    dfs(son[x],qtop);
    for(int i=head[x]; i; i=nxt[i]) {
        if(fa[x]!=to[i]&&to[i]!=son[x]) dfs(to[i],to[i]);
    }
}
int lca(int x,int y) {
    while(top[x]!=top[y]) (dep[top[x]]>=dep[top[y]])?x=fa[top[x]]:y=fa[top[y]];
    return dep[x]>dep[y]?y:x;
}
char ch[5];
int query(int u,int v,int lca,int lcafa,int l,int r,int kth) {
    if(l==r)return l;
    int sum=siz[ls[u]]+siz[ls[v]]-siz[ls[lca]]-siz[ls[lcafa]];
    int mid=l+r>>1;
    if(sum>=kth) return query(ls[u],ls[v],ls[lca],ls[lcafa],l,mid,kth);
    else return query(rs[u],rs[v],rs[lca],rs[lcafa],mid+1,r,kth-sum);
}
int main() {T=rd();
    n=rd();m=rd();q=rd();
    ecnt=cnt=tot=LSH=0;
    for(int i=1; i<=n; i++) scanf("%d",&p[i]),lsh[i]=p[i];
    sort(lsh+1,lsh+1+n);
    LSH=unique(lsh+1,lsh+1+n)-lsh-1;
    for(int i=1; i<=n; i++) p[i]=lower_bound(lsh+1,lsh+1+LSH,p[i])-lsh;
    for(int i=1,u,v; i<=m; i++)u=rd(),v=rd(),add(u,v),add(v,u);
    build(rt[0],1,LSH);
    for(int i=1; i<=n; i++) if(!SIZ[i]) root[++cnt]=i,dfs(i),dfs(i,i);
    int x,y,k,lastans=0;
    while(q--) {
        scanf("%s",ch);
        if(ch[0]=='Q') {
           x=rd()^lastans,y=rd()^lastans,k=rd()^lastans;
            int LCA=lca(x,y),LCAFA=fa[LCA];
            printf("%d\n",lastans=lsh[query(rt[x],rt[y],rt[LCA],rt[LCAFA],1,LSH,k)]);
        } 
        else if(ch[0]=='L') {
            x=rd()^lastans;y=rd()^lastans;
            if(SIZ[root[bl[x]]]<SIZ[root[bl[y]]]) swap(x,y);
            add(x,y),add(y,x);
            cnt=bl[x];
            SIZ[root[bl[x]]]+=SIZ[root[bl[y]]];dfs(x);dfs(x,top[x]);
        }
    }
}

猜你喜欢

转载自www.cnblogs.com/sdfzhsz/p/9509653.html
今日推荐