Kurskal重构树练习2——Peaks 加强版

本文详细解析了一种在重构树上应用主席树解决特定问题的算法,通过实例讲解了如何处理边权值限制下的第K大点权查询,涉及模块化编程、DFS序和主席树构建等关键步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

蒟蒻的垂死挣扎

这道题还是挺裸的,不过意义在于我1A了。。。

意义很重大有没有,100+行的代码啊。

 

只经过边权值小于等于balabala的边肯定就是很裸的重构树啦,然后求第K大的点权,在重构树上就是一棵子树,对于dfs序开主席树就可以了。写的时候理清楚思路,模块化编程啊,我习惯struct框起来,反正自己看着办就行。

 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
#define pir pair<int,int> 
#define ll long long
#define N 100100
#define ED 19
#define RG register
inline int read(){
    RG int x=0,t=1;RG char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    if(ch=='-')t=-1,ch=getchar();
    while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    return x*t;
}

int cnt,n,m,q,top,first[N<<1],val[N<<1],yyb[N],len,rt[N<<1],ht[N<<1];
struct mona { int nxt,en; int w; } s[N*10];
inline void Insert(int x,int y,int w) { s[++top]=(mona) { first[x],y,w },first[x]=top; }
struct Mona { int x,y; int w; } S[N*10];
inline bool cmp(Mona x,Mona y) { return x.w<y.w; }
struct HJTree{
	int cnt,ls[N*40],rs[N*40],sum[N*40];
	inline void Build(int l,int r,int &x,int y,int pos){
		x=++cnt,ls[x]=ls[y],rs[x]=rs[y],sum[x]=sum[y];
		if(!pos) return ; ++sum[x];
		if(l==r) return ; int mid=l+r>>1;
		if(pos<=mid) Build(l,mid,ls[x],ls[y],pos);
		else Build(mid+1,r,rs[x],rs[y],pos);
		sum[x]=sum[ls[x]]+sum[rs[x]];
	}
	inline int Query(int l,int r,int x,int y,int k){
		if(sum[y]-sum[x]<k) return -1;
		if(l==r) return yyb[l];	int mid=l+r>>1;
		int Sum=sum[rs[y]]-sum[rs[x]];
		if(Sum>=k) return Query(mid+1,r,rs[x],rs[y],k);
		else return Query(l,mid,ls[x],ls[y],k-Sum);
	}
} T;
struct BZ{
	int S[21][N<<1],cnt,dfn[N<<1],id[N<<1],to[N<<1];
	inline void Dfs(int k,int fa){
		S[0][k]=fa; for(RG int i=1;i<21;++i) S[i][k]=S[i-1][S[i-1][k]];
		dfn[k]=++cnt,id[cnt]=k,T.Build(1,len,rt[cnt],rt[cnt-1],ht[k]);
		for(RG int i=first[k];i;i=s[i].nxt)	Dfs(s[i].en,k); to[k]=cnt;
	}
	inline int Jump(int k,int hrd){
		for(RG int i=20;~i;--i)
			if(val[S[i][k]]<=hrd&&S[i][k]) k=S[i][k];
		return k;
	}
} B;
struct Kru{
	int fa[N<<1];
	inline int Find(int x) { if(fa[x]!=x) fa[x]=Find(fa[x]); return fa[x]; }
	inline void Kruskal(){
		for(RG int i=1;i<=n*2;++i) fa[i]=i;
		top=0; for(RG int i=1;i<=n;++i) first[i]=0;
		for(RG int i=1;i<=m;++i){
			int fx=Find(S[i].x),fy=Find(S[i].y),w=S[i].w;
			if(fx!=fy) fa[fx]=fa[fy]=++cnt,Insert(cnt,fx,w),Insert(cnt,fy,w),val[cnt]=w;
		}   B.Dfs(cnt,0);
	}
} K;

int main(){
	n=read(),m=read(),q=read(),cnt=n;
	for(RG int i=1;i<=n;++i) ht[i]=yyb[++len]=read();
	sort(yyb+1,yyb+1+len),len=unique(yyb+1,yyb+1+len)-yyb-1;
	for(RG int i=1;i<=n;++i) ht[i]=lower_bound(yyb+1,yyb+1+len,ht[i])-yyb;
	for(RG int i=1;i<=m;++i) S[i]=(Mona) { read(),read(),read() };
	sort(S+1,S+1+m,cmp),K.Kruskal(); RG int lst_ans=0;
	for(RG int i=1;i<=q;++i){
		int x=read(),hrd=read(),k=read();
		if(lst_ans!=-1) x^=lst_ans,hrd^=lst_ans,k^=lst_ans;
		int now=B.Jump(x,hrd),ans=T.Query(1,len,rt[B.dfn[now]-1],rt[B.to[now]],k);
		printf("%d\n",lst_ans=ans);
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值