• [BZOJ3551][ONTAK2010]Peaks加强版


    bzoj

    Description

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

    Input

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

    Output

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

    Sample Input

    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

    Sample Output

    6
    1
    -1
    8

    HINT

    「数据范围」(N<=10^5,M,Q<=5*10^5,h_i,c,x<=10^9)

    sol

    (Kruskal)重构树+树上倍增+主席树
    重构树之后,从一个点开始经过权值不超过(x)的边能够到达的点刚好是一个子树,所以就变成了区间(Kth)
    具体是哪一棵子树呢?考虑到重构树上非叶子节点的点权(也就是原图中的边权)是随深度单调的,所以可以写一个树上倍增求一个点最浅的权值小于等于(x)的祖先。
    注意(v)是节点编号!(x)是权值限制!
    剩下的就都是板子了。

    code

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    int gi()
    {
    	int x=0,w=1;char ch=getchar();
    	while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    	if (ch=='-') w=0,ch=getchar();
    	while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    	return w?x:-x;
    }
    const int N = 2e5+5;
    const int M = 5e5+5;
    struct edge{
    	int u,v,w;
    	bool operator < (const edge &b) const
    		{return w<b.w;}
    }E[M];
    struct president_tree{int ls,rs,num;}t[N*20];
    int n,m,q,num,h[N],o[N],len,to[N],nxt[N],head[N],cnt,fa[N],val[N],pa[20][N],dfn[N],low[N],ref[N],rt[N],tot,ans;
    void link(int u,int v){to[++cnt]=v;nxt[cnt]=head[u];head[u]=cnt;}
    int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
    void dfs(int u,int f)
    {
    	pa[0][u]=f;
    	for (int i=1;i<=19;++i)
    		pa[i][u]=pa[i-1][pa[i-1][u]];
    	if (u<=n) {dfn[u]=low[u]=++cnt;ref[cnt]=u;return;}
    	for (int e=head[u];e;e=nxt[e])
    		dfs(to[e],u),dfn[u]=min(dfn[u],dfn[to[e]]),low[u]=max(low[u],low[to[e]]);
    }
    void modify(int &x,int l,int r,int p)
    {
    	t[++tot]=t[x];t[x=tot].num++;
    	if (l==r) return;int mid=l+r>>1;
    	if (p<=mid) modify(t[x].ls,l,mid,p);
    	else modify(t[x].rs,mid+1,r,p);
    }
    int query(int A,int B,int l,int r,int k)
    {
    	if (l==r) return o[l];
    	int mid=l+r>>1,sum=t[t[A].rs].num-t[t[B].rs].num;
    	if (k<=sum) return query(t[A].rs,t[B].rs,mid+1,r,k);
    	else return query(t[A].ls,t[B].ls,l,mid,k-sum);
    }
    int solve(int x,int v,int k)
    {
    	int u=x;
    	for (int i=19;~i;--i)
    		if (pa[i][u]&&val[pa[i][u]]<=v) u=pa[i][u];
    	if (low[u]-dfn[u]+1<k) return -1;
    	return query(rt[low[u]],rt[dfn[u]-1],1,len,k);
    }
    int main()
    {
    	n=num=gi();m=gi();q=gi();
    	for (int i=1;i<=n;++i) fa[i]=i,h[i]=o[++len]=gi();
    	sort(o+1,o+len+1);len=unique(o+1,o+len+1)-o-1;
    	for (int i=1;i<=n;++i) h[i]=lower_bound(o+1,o+len+1,h[i])-o;
    	for (int i=1;i<=m;++i) E[i]=(edge){gi(),gi(),gi()};
    	sort(E+1,E+m+1);
    	for (int i=1;i<=m;++i)
    		if (find(E[i].u)^find(E[i].v))
    		{
    			++num;
    			val[num]=E[i].w;link(num,find(E[i].u));link(num,find(E[i].v));
    			fa[find(E[i].u)]=fa[find(E[i].v)]=fa[num]=num;
    		}
    	memset(dfn,63,sizeof(dfn));cnt=0;
    	for (int i=1;i<=num;++i) if (fa[i]==i) dfs(i,0);
    	for (int i=1;i<=n;++i) modify(rt[i]=rt[i-1],1,len,h[ref[i]]);
    	while (q--)
    	{
    		int x=gi(),v=gi(),k=gi();
    		if (ans!=-1) v^=ans,x^=ans,k^=ans;
    		printf("%d
    ",ans=solve(x,v,k));
    	}
    	return 0;
    }
    
  • 相关阅读:
    题解-bzoj1283序列 & bzoj4842 [Neerc2016]Delight for a Cat
    题解-bzoj4061 CERC-2012Farm and Factory
    题解-bzoj3569 DZY Loves Chinese II
    题解-bzoj3901 棋盘游戏
    题解-PKUWC2018 Minimax
    题解-PKUWC2018 Slay the Spire
    题解-PKUWC2018 随机算法
    题解-PKUWC2018 随机游走
    bzoj1010[HNOI2008]玩具装箱toy 斜率优化dp
    bzoj1096[ZJOI2007]仓库建设 斜率优化dp
  • 原文地址:https://www.cnblogs.com/zhoushuyu/p/8630582.html
Copyright © 2020-2023  润新知