zoukankan      html  css  js  c++  java
  • [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
    ",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]);
            }
        }
    }
    
    我是咸鱼。转载博客请征得博主同意Orz
  • 相关阅读:
    程序设计网站综合
    .net 获取url的方法(转)
    制作简单的语音识别系统(阅读文章)
    创建 WPF 不规则窗口
    高斯消元法
    How many ways(DFS记忆化搜索)
    I NEED A OFFER!
    免费馅饼
    N^N(Leftmost Digit )
    Common Subsequence
  • 原文地址:https://www.cnblogs.com/sdfzhsz/p/9509653.html
Copyright © 2011-2022 走看看