其他分享
首页 > 其他分享> > P4197 Peaks kruskal 重构树

P4197 Peaks kruskal 重构树

作者:互联网

这题有个加强版 是在线的
离线可以线段树合并 fhq合并(没试过后面这个)
在线的话得用新科技了 那就是kruskal重构树
先按最小生成树重构 然后就是一个大根堆
我们发现 v这个点向上找到的最后一个<=x的祖先
这个祖先的所有儿子 都是v在x的限制下可达的
然后就是主席树板子了(好久没写主席树。。)

#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+100;
const int M = 5e5+100;
int n,m,q;
struct edge{
	int u,v,w;
	bool operator < (const edge&a)const{
		return w<a.w;
	}
}e[M];
int fa[N],h[N],hh,has[N],f[N][22],dep[N],val[N],cnt;
vector<int>to[N];
int st[N],ed[N];
int ls[N*30],rs[N*30],sum[N*30],rt[N],tot;
void add_edge(int x,int y){
	to[x].push_back(y);
	to[y].push_back(x);
}
int getfa(int x){
	return fa[x]==x?x:fa[x]=getfa(fa[x]);
}
void update(int &o,int las,int l,int r,int pos){
	o=++tot;
	sum[o]=sum[las]+1;
	if(l==r) return;
	int mid = l+r>>1;
	if(pos<=mid) rs[o]=rs[las],update(ls[o],ls[las],l,mid,pos);
	else ls[o]=ls[las],update(rs[o],rs[las],mid+1,r,pos);
}
int query(int ql,int qr,int l,int r,int k){
	if(l==r) return l;
	int tt=sum[rs[qr]]-sum[rs[ql]],mid=l+r>>1;
	//printf("l=%d r=%d tt=%d\n",l,r,tt);
	if(k<=tt) return query(rs[ql],rs[qr],mid+1,r,k);
	else return query(ls[ql],ls[qr],l,mid,k-tt);
}
void dfs(int u,int ff){
	dep[u]=dep[ff]+1;
	f[u][0]=ff;
	st[u]=++cnt;
	for(int i = 1; i <= 20; i++){
		if(dep[u]<(1<<i)) break;
		else f[u][i]=f[f[u][i-1]][i-1];
	}
	if(u<=n){
		update(rt[st[u]],rt[st[u]-1],1,hh,h[u]);
	}else{
		rt[st[u]]=rt[st[u]-1];
	}
	for(auto v:to[u]){
		if(v==ff) continue;
		dfs(v,u);
	}	
	ed[u]=cnt;
}
int main(){
	val[0]=1e9+100;
	scanf("%d%d%d",&n,&m,&q);
	for(int i = 1; i <= n; i++)
	scanf("%d",&h[i]),has[i]=h[i];
	sort(has+1,has+1+n);
	hh=unique(has+1,has+1+n)-has-1;
	for(int i = 1; i <= n; i++)
	h[i]=lower_bound(has+1,has+1+hh,h[i])-has;
	for(int i = 1; i <= 2*n; i++) fa[i]=i;
	for(int i = 1; i <= m; i++){
		scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
	}
	sort(e+1,e+1+m);
	int id=n;
	for(int i = 1; i <= m; i++){
		int fu=getfa(e[i].u),fv=getfa(e[i].v);
		if(fu!=fv){
			fa[fu]=fa[fv]=++id;
			val[id]=e[i].w;
			add_edge(fu,id);
			add_edge(fv,id);
		}
	}
	for(int i = 1; i <= n; i++) if(!st[i]) dfs(getfa(i),0);
	for(int i = 1; i <= q; i++){
		int v,x,k;
		scanf("%d%d%d",&v,&x,&k);
		for(int i = 20; i >= 0; i--){
			if(dep[v]<(1<<i)) continue;
			if(val[f[v][i]]<=x) v=f[v][i];
		}
		if(sum[rt[ed[v]]]-sum[rt[st[v]-1]]<k){
			puts("-1");
		}else{
			printf("%d\n",has[query(rt[st[v]-1],rt[ed[v]],1,hh,k)]);
		}
	}
	return 0;
}
/*
4 3 100
1 2 3 4
1 2 8
2 4 1
1 3 4
1 8 2
*/

标签:return,Peaks,int,kruskal,fa,edge,P4197,const,sum
来源: https://www.cnblogs.com/League-of-cryer/p/14210301.html