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
    ");
    		
    	}
    }
    
  • 相关阅读:
    手机截屏雷阵雨
    2010年5月20日 用户的数据永远不会靠谱
    2010年5月17日 OCD
    2010年8月9日 流水账
    2010年5月19日 借鉴
    立表为据
    2010年6月2日 回来
    不重视小C打屁屁
    2010年8月16日 知行合一
    2010年5月18日 小细节大隐患
  • 原文地址:https://www.cnblogs.com/ZUTTER/p/9835735.html
Copyright © 2011-2022 走看看