[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*4)
struct gg{
    int u,v,w;
}side1[maxm];
int n,m,q,ncnt,h[maxn],fa[maxq],dep[maxq],f[maxnq][21],size[maxq],seq[maxq],poi;
/*--------------------------------*/
int sorted[maxq],ls[maxq<<5],rs[maxq<<5],len,idx,sum[maxq<<5],rt[maxq],cnt;
/*--------------------------------*/
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 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){
    update(rt[cnt++],1,len,getid(h[u]));
    seq[++poi]=u;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<side2[u].size();i++){
        int v=side2[i].v;if(v==g)return;dfs1(v,u);
    }
    return;
}
int lca(int u,int v){
    if(dep[u]<dep[v])swap(u,v);
    for(int i=20;i>=1;i--)if(dep[f[u][i]]>=dep[v])u=f[u][i];
    if(u==v)return u;
    for(int i=20;i>=1;i--)if(f[u][i]!=f[v][i]){u=f[u][i];v=f[v][i];}
    return f[u][0];
}
vector<int>side2[maxn];
int build(int l,int r){
    int now=++idx;int mid=(l+r)>>1;
    ls[now]=build(l,mid);rs[now]=build(mid+1,r);
    return now;
}
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 main(){
    scanf("%d%d%d",&n,&m,&q);
    for(int i=1;i<=n;i++)scanf("%d",&h[i]);
    for(int i=1;i<=m;i++)scanf("%d%d%d",&side1[i].u,&side1[i].v,&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(x)==get(y))continue;
        uni(u,v,w);
    }
    sort(h+1,h+1+n);len=uniqua(h+1,h+1+n)-h-1;rt[0]=build(1,len);
    dfs1(ncnt,0);
}

猜你喜欢

转载自www.cnblogs.com/GavinZheng/p/10896638.html
今日推荐