zoukankan      html  css  js  c++  java
  • [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));
        }
     
    }
    
  • 相关阅读:
    prototype.js超强的javascript类库
    MySQL Server Architecture
    Know more about RBA redo block address
    MySQL无处不在
    利用Oracle Enterprise Manager Cloud Control 12c创建DataGuard Standby
    LAMP Stack
    9i中DG remote archive可能导致Primary Database挂起
    Oracle数据库升级与补丁
    Oracle为何会发生归档日志archivelog大小远小于联机重做日志online redo log size的情况?
    Oracle Ksplice如何工作?How does Ksplice work?
  • 原文地址:https://www.cnblogs.com/GavinZheng/p/10896638.html
Copyright © 2011-2022 走看看