• bzoj3123: [Sdoi2013]森林


    Description

     

    Input

    第一行包含一个正整数testcase,表示当前测试数据的测试点编号。保证1≤testcase≤20。 
    第二行包含三个整数N,M,T,分别表示节点数、初始边数、操作数。第三行包含N个非负整数表示 N个节点上的权值。 
     接下来 M行,每行包含两个整数x和 y,表示初始的时候,点x和点y 之间有一条无向边, 接下来 T行,每行描述一个操作,格式为“Q x y k”或者“L x y ”,其含义见题目描述部分。

    Output

    对于每一个第一类操作,输出一个非负整数表示答案。 

    对每个联通块用倍增维护树的结构,可持久化线段树支持查询树链上第k小,修改时可以启发式合并
    #include<cstdio>
    #include<algorithm>
    const int N=80007;
    char buf[20000007],*ptr=buf-1;
    #define G *++ptr
    int _(){
        int x=0,c=G;
        while(c<48)c=G;
        while(c>47)x=x*10+c-48,c=G;
        return x;
    }
    int _c(){
        int c=G;
        while(c<33)c=G;
        return c;
    }
    int n,m,q,la=0,v[N],vs[N],f[N],siz[N],rt[N];
    int es[N*2],enx[N*2],e0[N],ep=2;
    int fa[N][20],dep[N];
    int ch[N*400][2],sz[N*400],mp=0;
    int gf(int x){
        while(x!=f[x])x=f[x]=f[f[x]];
        return x;
    }
    int ins(int w,int x){
        int u=++mp,u0=u;
        for(int i=16,d;~i;--i){
            d=x>>i&1;
            ch[u][d^1]=ch[w][d^1];
            sz[u=ch[u][d]=++mp]=sz[w=ch[w][d]]+1;
        }
        return u0;
    }
    void f1(int w,int pa=0){
        dep[w]=dep[fa[w][0]=pa]+1;
        rt[w]=ins(rt[pa],v[w]);
        for(int i=1;i<17;++i)fa[w][i]=fa[fa[w][i-1]][i-1];
        for(int i=e0[w];i;i=enx[i]){
            int u=es[i];
            if(u!=pa)f1(u,w);
        }
    }
    void mg(int a,int b,bool d){
        int x=gf(a),y=gf(b);
        if(siz[x]>siz[y])std::swap(x,y),std::swap(a,b);
        siz[f[x]=y]+=siz[x];
        if(d)f1(a,b);
        es[ep]=a;enx[ep]=e0[b];e0[b]=ep++;
        es[ep]=b;enx[ep]=e0[a];e0[a]=ep++;
    }
    int up(int x,int d){
        for(int t=0;d;d>>=1,++t)if(d&1)x=fa[x][t];
        return x;
    }
    int lca(int a,int b){
        if(dep[a]<dep[b])std::swap(a,b);
        a=up(a,dep[a]-dep[b]);
        if(a!=b){
            for(int i=16;~i;--i)if(fa[a][i]!=fa[b][i])a=fa[a][i],b=fa[b][i];
            return fa[a][0];
        }
        return a;
    }
    void query(int w1,int w2,int w3,int w4,int k){
        int x=0;
        for(int i=16;~i;--i){
            int s=sz[ch[w1][0]]+sz[ch[w2][0]]-sz[ch[w3][0]]-sz[ch[w4][0]];
            if(s>=k){
                w1=ch[w1][0];
                w2=ch[w2][0];
                w3=ch[w3][0];
                w4=ch[w4][0];
            }else{
                x|=1<<i;
                k-=s;
                w1=ch[w1][1];
                w2=ch[w2][1];
                w3=ch[w3][1];
                w4=ch[w4][1];
            }
        }
        printf("%d
    ",la=vs[x]);
    }
    int main(){
        buf[fread(buf,1,sizeof(buf),stdin)]=0;
        _();
        n=_();m=_();q=_();
        for(int i=1;i<=n;++i)vs[i]=v[i]=_(),siz[i]=dep[i]=1,f[i]=i;
        std::sort(vs+1,vs+n+1);
        for(int i=1;i<=n;++i)v[i]=std::lower_bound(vs+1,vs+n+1,v[i])-vs;
        while(m--)mg(_(),_(),0);
        for(int i=1;i<=n;++i)if(i==f[i])f1(i,0);
        while(q--){
            if(_c()=='Q'){
                int x=_()^la,y=_()^la,k=_()^la,z=lca(x,y);
                query(rt[x],rt[y],rt[z],rt[fa[z][0]],k);
            }else{
                int x=_()^la,y=_()^la;
                mg(x,y,1);
            }
        }
        return 0;
    }
  • 相关阅读:
    jQuery 如何存储,获取和删除 Cookies
    mysql调用存储过程出现Illegal mix of collations错误
    vim IDE
    android 播放Raw文件夹下的音乐文件
    7种形式的Android Dialog使用举例
    Chronometer 计时器使用
    获取屏幕,适应屏幕
    android 碎片
    安卓开发者必备的42个链接
    自定义TabActivity,TabActivity的美化
  • 原文地址:https://www.cnblogs.com/ccz181078/p/6446026.html
Copyright © 2020-2023  润新知