zoukankan      html  css  js  c++  java
  • P3302 [SDOI2013]森林

    树上第k小是裸题,然后连边操作显然只能用启发式合并

    连边之后重构小的部分,重构一遍主席树和倍增数组,水的一批(逃

    #include<bits/stdc++.h>
    #define il inline
    #define vd void
    typedef long long ll;
    il int gi(){
        int x=0,f=1;
        char ch=getchar();
        while(!isdigit(ch)){
            if(ch=='-')f=-1;
            ch=getchar();
        }
        while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
        return x*f;
    }
    int w[80010],W[80010],nw,FA[80010],SZ[80010];
    il int hd(int x){return FA[x]==x?x:FA[x]=hd(FA[x]);}
    int fir[80010],dis[160010],nxt[160010],id;
    il vd link(int a,int b){nxt[++id]=fir[a],fir[a]=id,dis[id]=b;}
    int st[17][80010],dep[80010];
    int rt[80010],ls[10000010],rs[10000010],sum[10000010],cnt;
    #define mid ((l+r)>>1)
    il vd build(int&x,int l,int r){
        x=++cnt;if(l==r)return;
        build(ls[x],l,mid),build(rs[x],mid+1,r);
    }
    il vd update(int&x,int l,int r,const int&p){
        ++cnt,sum[cnt]=sum[x],ls[cnt]=ls[x],rs[cnt]=rs[x],x=cnt;
        ++sum[x];if(l==r)return;
        if(p<=mid)update(ls[x],l,mid,p);
        else update(rs[x],mid+1,r,p);
    }
    il int query(int&a,int&b,int&c,int&d,int l,int r,int k){
        if(l==r)return l;
        if(sum[ls[a]]+sum[ls[b]]-sum[ls[c]]-sum[ls[d]]<k)return query(rs[a],rs[b],rs[c],rs[d],mid+1,r,k-(sum[ls[a]]+sum[ls[b]]-sum[ls[c]]-sum[ls[d]]));
        else return query(ls[a],ls[b],ls[c],ls[d],l,mid,k);
    }
    #undef mid
    il vd dfs(int x,int fa){
        rt[x]=rt[fa];dep[x]=dep[fa]+1;update(rt[x],1,nw,W[x]);
        st[0][x]=fa;for(int i=1;i<17;++i)st[i][x]=st[i-1][st[i-1][x]];
        for(int i=fir[x];i;i=nxt[i])if(dis[i]!=fa)dfs(dis[i],x);
    }
    il vd merge(int x,int y){
        if(SZ[hd(x)]<SZ[hd(y)])std::swap(x,y);
        link(x,y),link(y,x),dfs(y,x);SZ[hd(x)]+=SZ[hd(y)],FA[hd(y)]=hd(x);
    }
    il int LCA(int x,int y){
        if(dep[x]<dep[y])std::swap(x,y);
        int c=dep[x]-dep[y];
        for(int i=16;~i;--i)if(c&(1<<i))x=st[i][x];
        for(int i=16;~i;--i)if(st[i][x]^st[i][y])x=st[i][x],y=st[i][y];
        if(x^y)x=st[0][x];return x;
    }
    int main(){
    #ifndef ONLINE_JUDGE
        freopen("in.in","r",stdin);
        freopen("out.out","w",stdout);
    #endif
        gi();
        int n=gi(),m=gi(),q=gi(),x,y,k;
        for(int i=1;i<=n;++i)W[i]=w[i]=gi();
        std::sort(w+1,w+n+1);nw=std::unique(w+1,w+n+1)-w-1;
        for(int i=1;i<=n;++i)W[i]=std::lower_bound(w+1,w+nw+1,W[i])-w;
        build(rt[0],1,nw);
        for(int i=1;i<=n;++i)rt[i]=rt[0],update(rt[i],1,nw,W[i]);
        for(int i=1;i<=n;++i)FA[i]=i,SZ[i]=1,dep[i]=1;
        while(m--)x=gi(),y=gi(),merge(x,y);
        int lst=0;char opt[3];
        while(q--){
            scanf("%s",opt);
            if(opt[0]=='Q'){
                x=gi()^lst,y=gi()^lst,k=gi()^lst;
                int lca=LCA(x,y);
                printf("%d
    ",lst=w[query(rt[x],rt[y],rt[lca],rt[st[0][lca]],1,nw,k)]);
            }else x=gi()^lst,y=gi()^lst,merge(x,y);
        }
        return 0;
    }
    
  • 相关阅读:
    maven工程下的“run as application”
    Spark机器配置计算
    数学思路
    关联和依赖
    spark数据倾斜
    windows的DOS窗口如何修改大小
    MySQL的索引创建、删除
    使用composer命令创建laravel项目命令详解
    Windows平台查看端口占用情况
    使用composer安装laravel
  • 原文地址:https://www.cnblogs.com/xzz_233/p/10192624.html
Copyright © 2011-2022 走看看