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
    ");
    		
    	}
    }
    
  • 相关阅读:
    字节码编程,Javassist篇四《通过字节码插桩监控方法采集运行时入参出参和异常信息》
    字节码编程,Javassist篇三《使用Javassist在运行时重新加载类「替换原方法输出不一样的结果」》
    字节码编程,Javassist篇二《定义属性以及创建方法时多种入参和出参类型的使用》
    字节码编程,Javassist篇一《基于javassist的第一个案例helloworld》
    CPU瞒着内存竟干出这种事
    可怕!CPU竟成了黑客的帮凶!
    完了!CPU一味求快出事儿了!
    如果平行宇宙也有编程语言
    你离黑客的距离,就差这20个神器了
    哈希表哪家强?几大编程语言吵起来了!
  • 原文地址:https://www.cnblogs.com/ZUTTER/p/9835735.html
Copyright © 2011-2022 走看看