zoukankan      html  css  js  c++  java
  • P4197 Peaks

    题目描述

    在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 imes 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)大节点即可


    恩......
    enter image description hereenter image description hereenter image description hereenter image description hereenter image description hereenter image description hereenter image description hereenter image description hereenter image description hereenter image description hereenter image description hereenter image description hereenter image description here


    #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
    ",pp[k]);
    		else printf("-1
    ");
    		
    	}
    }
    
  • 相关阅读:
    Paxos算法理解
    JavaScript笔记
    JVM基础知识(二)
    JVM基础知识(一)
    书单
    centos6.3环境下升级python及MySQLdb的安装
    winform中button的image属性无法更改
    未能找到任何适合于指定的区域性或非特定区域性的资源
    Spring注解开发第十二讲--@Profile注解讲解
    Spring注解驱动第十一讲--引用Spring底层组件
  • 原文地址:https://www.cnblogs.com/ZUTTER/p/9835735.html
Copyright © 2011-2022 走看看