码迷,mamicode.com
首页 > 其他好文 > 详细

P4197 Peaks

时间:2018-10-23 14:35:35      阅读:173      评论:0      收藏:0      [点我收藏+]

标签:space   eof   static   algo   mat   5*   线段   dfs   持久化   

题目描述

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

输入输出格式

输入格式:

第一行三个数N,M,Q。 第二行N个数,第ii个数为\(h_i\) 接下来MM行,每行33个数a,b,c,表示从a到b有一条困难值为c的双向路径。 接下来Q行,每行三个数v,x,k,表示一组询问。

输出格式:

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

输入输出样例

输入样例#1: 复制

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

输出样例#1: 复制

6
1
-1
8

说明

数据范围

\(N \le 10^5, 0 \le M,Q \le 5\times 10^5,h_i,c,x \le 10^9\)


kruskal重构树
对于每一个节点其子树的叶子就是在这个点的权值内能相互到达的点
按照dfs序建可持久化权值线段树,dfs序\(u\)\(u+size[u]\)内每个点的增量就是\(pre[u]\)子树的点
每次查询时把\(v\)倍增跳到\(\leq x\)的最大值,在\((dfn[x]+size[x])-(dfn[x]-1)\)的线段树内找第\(k\)大节点即可


恩......
技术分享图片技术分享图片技术分享图片技术分享图片技术分享图片技术分享图片技术分享图片技术分享图片技术分享图片技术分享图片技术分享图片技术分享图片技术分享图片


#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define M (200005*10)
#define N 200005
#define LL long long
#define max(a,b) ((a)>(b)? (a):(b))
#define min(a,b) ((a)<(b)? (a):(b))

using namespace std;

int top[N],d[M],h[N],ls[M],rs[M],n,m,q,cnt,f[N],edge[N],cnt1,y;
int head[N],ver[N],nex[N],dfn[N],df,pre[M],g,z[N],pp[N],v,x,k,bz[N][26],s[N],az[N][26];
struct vv{  int f,t,edge;} a[M];
inline bool cmp(vv a,vv b) {return a.edge<b.edge;}

inline char gc()
{
    static char now[1<<22],*S,*T;
    if (T==S)
    {
        T=(S=now)+fread(now,1,1<<22,stdin);
        if (T==S) return EOF;
    }
    return *S++;
}
inline int gtt()
{
    register int x=0,f=1;
    register char ch=gc();
    while(!isdigit(ch))
    {
        if (ch==‘-‘) f=-1;
        ch=gc();
    }
    while(isdigit(ch)) x=(x<<1)+(x<<3)+ch-‘0‘,ch=gc();
    return x*f;
}
inline void add(int x,int y)
{
    cnt1+=1;
    ver[cnt1]=y; nex[cnt1]=head[x]; head[x]=cnt1;
}

int ff(int x)
{
    if(f[x]==x) return x;
    f[x]=ff(f[x]);
    return f[x];
}

inline void kru()
{
    for(int i=1;i<=m;i++)
    {
        int w=ff(a[i].f), e=ff(a[i].t);
        if(w!=e)
        {
            f[w]=f[e]=++n;
            add(n,w); add(n,e);
            edge[n]=a[i].edge;
        }
    }
}

void dfs(int now)
{
    bz[now][0]=edge[now]; 
    s[now]=1; dfn[now]=++df; pre[df]=now;
    for(int i=head[now];i;i=nex[i])
    {
        int t=ver[i];
        dfs(t);
        bz[t][1]=edge[now];
        az[t][1]=now;
        s[now]+=s[t];
    }
}

void built(int now,int l,int r,int pre,int z)
{
    if(l==r)
    {
        d[now]=d[pre]+1;
        return;
    }
    int mid=(l+r)>>1; ls[now]=ls[pre]; rs[now]=rs[pre];
    if(z<=mid)
    {
        ls[now]=++cnt;
        built(ls[now],l,mid,ls[pre],z);
    }
    if(z>mid)
    {
        rs[now]=++cnt;
        built(rs[now], mid+1, r, rs[pre], z);
    }
    d[now]=d[ls[now]]+d[rs[now]];
}

void built1(int now,int l,int r)
{
    if(l==r) return;
    ls[now]=++cnt; rs[now]=++cnt;
    int mid=(l+r)>>1;
    built1(ls[now], l, mid);
    built1(rs[now], mid+1, r);
}

int find(int now1,int now2,int l,int r,int z)
{
    if(l==r) return l; 
    if(d[now2]-d[now1]<z) return -1;
    int mid=(l+r)>>1;
    if(d[rs[now2]]-d[rs[now1]]>=z) return find(rs[now1], rs[now2], mid+1, r, z);
    return find(ls[now1], ls[now2], l, mid, z-d[rs[now2]]+d[rs[now1]]);
}

int main()
{
    n=gtt(); m=gtt(); q=gtt();  g=n;
    for(int i=1;i<=4*n;i++) f[i]=i;

    for(int i=1;i<=n;i++) h[i]=gtt(), z[i]=h[i];
    sort(z+1,z+1+n);
    int mm=unique(z+1,z+1+n)-z-1;
    for(int i=1;i<=n;i++) 
    {
        k=lower_bound(z+1,z+1+mm,h[i])-z;
        pp[k]=h[i]; h[i]=k;
    }
    
    for(int i=1;i<=m;i++){ a[i].f=gtt(); a[i].t=gtt(); a[i].edge=gtt();}
    sort(a+1,a+1+m,cmp); kru(); 
    
    for(int i=n;i;i--)  if(!dfn[i]) dfs(i);
    
    if(g!=1){top[1]=1; cnt=1; built1(1,1,mm);}
    else {top[1]=1; cnt=1;built(cnt,1,mm,0,h[pre[1]]);}
    
    for(int i=2;i<=n;i++) 
        if(pre[i]<=g) 
        {
            top[i]=++cnt;
            built(cnt,1,mm,top[i-1],h[pre[i]]);
        }
        else top[i]=top[i-1];
    
    for(int i=2;i<=25;i++) 
        for(int j=1;j<=n;j++) 
            bz[j][i]=bz[az[j][i-1]][i-1], az[j][i]=az[az[j][i-1]][i-1];
        
    for(int i=1;i<=q;i++)
    {
        v=gtt(); x=gtt(); k=gtt();
        for(int j=25;j>=1;j--) if(bz[v][j]<=x && az[v][j]) v=az[v][j];
        k=find(top[dfn[v]-1],top[dfn[v]+s[v]-1],1,mm,k);
        if(k!=-1)printf("%d\n",pp[k]);
        else printf("-1\n");
        
    }
}

P4197 Peaks

标签:space   eof   static   algo   mat   5*   线段   dfs   持久化   

原文地址:https://www.cnblogs.com/ZUTTER/p/9835735.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!