• [BZOJ3551]ONTAK2010-Peaks加强版


    [BZOJ3551]ONTAK2010-Peaks加强版

    题面

    在Bytemountains有N座山峰,每座山峰有他的高度h_i。有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询问从点v开始只经过困难值小于等于x的路径所能到达的山峰中第k高的山峰,如果无解输出-1。

    Input

    第一行三个数N,M,Q。

    第二行N个数,第i个数为h_i

    接下来M行,每行3个数a b c,表示从a到b有一条困难值为c的双向路径。

    接下来Q行,每行三个数v x k,表示一组询问。v=v xor lastans,x=x xor lastans,k=k xor lastans。如果lastans=-1则不变。

    Output

    对于每组询问,输出一个整数表示答案。

    Sample Input

    10 11 4
    1 2 3 4 5 6 7 8 9 10
    1 4 4
    2 5 3
    9 8 2
    7 8 10
    7 1 4
    6 7 1
    6 4 8
    2 1 5
    10 8 10
    3 4 7
    3 4 6
    1 5 2
    1 5 6
    1 5 8
    8 9 2

    Sample Output

    6
    1
    -1
    8

    Hint

    【数据范围】N<=10^5, M,Q<=5*10 ^ 5,h_i,c,x<=10^9。

    思路

    在Kruscal重构树上的边点 (x) 的子树代表最大边权不超过 (num[x]) 的点组成的连通块。

    那么很显然,从“v开始,困难值小于等于x"意思就是在v的所有祖先中,点权小于等于x,深度最浅的点的子树组成的连通块。

    那么求第k大就相当于是在给定子树内求第k大。子树第k大可以用dfs序把树形结构转换成线性结构。那么就相当于是一个区间k大的问题了。主席树经典例题。

    代码

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<vector>
    using namespace std;
    #define maxn (int)(1e5+100)
    #define maxm (int)(5*1e5+100)
    #define maxq (maxn*2)
    struct gg{
        int u,v,w;
    }side1[maxm];
    int
    n,m,q,ncnt,h[maxn],fa[maxq],dep[maxq],f[maxq][21],size[maxq],seq[maxq],poi,num[maxq];
    /*--------------------------------*/
    int sorted[maxq],ls[maxq*20],rs[maxq*20],len,idx,sum[maxq*20],rt[maxq],cnt;
    /*--------------------------------*/
    vector<int>side2[maxq];
    inline void read(int &x) {
      x = 0; char c = getchar();
      while (c < '0' || c > '9') c = getchar();
      while ('0' <= c && c <= '9') x = (x << 1) + (x << 3) + c - '0', c = getchar();
    }
    bool cop(gg x,gg y){return x.w<y.w;}
    int getid(int x){
        return lower_bound(h+1,h+1+len,x)-h;
    }
    int update(int last,int l,int r,int num){
        int now=++idx;int mid=(l+r)>>1;
        sum[now]=sum[last]+1;ls[now]=ls[last];rs[now]=rs[last];
        if(l==r)return now;
        if(num<=mid){ls[now]=update(ls[last],l,mid,num);}
        else{rs[now]=update(rs[last],mid+1,r,num);}
        return now;
    }
    int lastans=0;
    int get(int x){
        if(fa[x]==x)return x;
        fa[x]=get(fa[x]);
        return fa[x];
    }
    void uni(int u,int v,int w){
        int f_u=get(u),f_v=get(v);
        num[++ncnt]=w;
        side2[ncnt].push_back(f_u),side2[ncnt].push_back(f_v);side2[f_u].push_back(ncnt);
        side2[f_v].push_back(ncnt);size[ncnt]=size[f_u]+size[f_v];
        fa[f_u]=fa[f_v]=fa[ncnt]=ncnt;
        return;
    }
    void dfs1(int u,int g){
       if((int)(side2[u].size())==1){seq[u]=++poi;
       rt[cnt+1]=update(rt[cnt],1,len,getid(sorted[u]));cnt++;}
       dep[u]=dep[g]+1;f[u][0]=g;
        for(int i=1;i<=20;i++)f[u][i]=f[f[u][i-1]][i-1];
        for(int i=0;i<(int)(side2[u].size());i++){
            int v=side2[u][i];if(v==g)return;dfs1(v,u);
        }
        return;
    }
    int build(int l,int r){
        int now=++idx;int mid=(l+r)>>1;
        if(l==r)return now;
        ls[now]=build(l,mid);rs[now]=build(mid+1,r);
        return now;
    }
    int dfs2(int u,int lim,int last){
        if(num[u]>lim)return 0;
        if(u==ncnt)return u;
        for(int i=20;i>=0;i--){
            if(num[f[u][i]]<=lim&&f[u][i]!=0){u=f[u][i];}
        }
        return u;
    }
    inline int query(int last,int now,int k,int l,int r){
        if(l==r)return l;
        int mid=(l+r)>>1;
        int val=sum[ls[now]]-sum[ls[last]];
        if(k<=val){return query(ls[last],ls[now],k,l,mid);}
        else{return query(rs[last],rs[now],k-val,mid+1,r);}
    }
    int get_kth(int l,int r,int k){
        if(r-l+1<k){lastans=-1;return -1;}
        k=(r-l+2)-k;
        lastans=h[query(rt[l-1],rt[r],k,1,len)];
        return lastans;
    }
    int main(){
        read(n),read(m),read(q);
        for(int i=1;i<=n;i++){read(h[i]);sorted[i]=h[i];}
        for(int i=1;i<=m;i++){read(side1[i].u),read(side1[i].v),read(side1[i].w);}
        sort(side1+1,side1+1+m,cop);for(int i=1;i<=n;i++){fa[i]=i;size[i]=1;}ncnt=n;
        for(int i=1;i<=m;i++){
            int u=side1[i].u,v=side1[i].v,w=side1[i].w;
            if(get(u)==get(v))continue;
            uni(u,v,w);
        }
        sort(h+1,h+1+n);len=unique(h+1,h+1+n)-h-1;rt[0]=build(1,len);
        dfs1(ncnt,0);
        for(int i=1;i<=q;i++){
            int a,b,c;read(a),read(b),read(c);
            if(lastans!=-1){a^=lastans;b^=lastans;c^=lastans;}
            if(size[get(a)]<c){lastans=-1;printf("-1
    ");continue;}
            int top=dfs2(side2[a][0],b,a);
            if(!top){lastans=-1;printf("-1
    ");continue;}
            int buttom=top,last=top;
            while(side2[buttom][0]!=last){last=buttom,buttom=side2[buttom][0];}
            printf("%d
    ",get_kth(seq[buttom],seq[buttom]+size[top]-1,c));
        }
     
    }
    
  • 相关阅读:
    项目上线之期初数据调整
    系统升级时,数据库脚本执行注意事项,血的教训
    数据精度问题的处理
    系统发布说明文档
    SQLServer中数据库文件的存放方式,文件和文件组
    数据库的持续集成和版本控制
    SQL Server 远程链接服务器详细配置【转载】
    批处理中的IF ERRORLEVEL
    asp.net用url重写URLReWriter实现任意二级域名
    关于excel导入access问题(已解决)
  • 原文地址:https://www.cnblogs.com/GavinZheng/p/10896638.html
Copyright © 2020-2023  润新知