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
    ");
    		
    	}
    }
    
  • 相关阅读:
    Android应用程序组件Content Provider在应用程序之间共享数据的原理分析
    Android录制声音(二)录音输输出格式
    Firemacs:像垄断 Emacs 一样垄断 Firefox
    超棒的 KDE 面板小序次-Kirocker Music Display
    特征化设置你的linux环境
    软响铃 ── 把 beep 换成音乐
    简化 Picasa 图片上传
    Moonlight:Linux 平台上的 Silverlight
    Wine 0.9.39
    本钱与linux
  • 原文地址:https://www.cnblogs.com/ZUTTER/p/9835735.html
Copyright © 2011-2022 走看看