(南昌邀请网络赛) J.Distance on the tree (树链剖分+主席树)

本文介绍了一种使用树链剖分和主席树的数据结构算法,用于解决树上的路径查询问题,具体为查询从节点ui到vi的路径上边权小于等于ki的边的数量。通过树链剖分将树转换为链,再利用主席树进行区间查询,实现了高效的解决方案。

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

传送门

题意:给一颗树,m次查询ui->vi这条链中边权小于等于ki的边数。

解:树链剖分+主席树思路很清晰,可以解决;(又因为数组开小了而狂T不止

#include<bits/stdc++.h>
#define il inline
#define pb push_back
#define ms(_data,v) memset(_data,v,sizeof(_data))
#define SZ(a) int((a).size())
#define mid ((l+r)>>1)
using namespace std;
typedef long long ll;
const ll inf=0x3f3f3f3f;
const int N=2e5+5; 
template <typename _Tp> il void read(_Tp&x) {
	char ch;bool flag=0;x=0;
	while(ch=getchar(),!isdigit(ch)) if(ch=='-')flag=1;
	while(isdigit(ch)) x=x*10+ch-'0',ch=getchar();
	if(flag) x=-x;
}
//il int Add(ll &x,ll y) {return x=x+y>=mod?x+y-mod:x+y;}
//il int Mul(ll &x,ll y) {return x=x*y>=mod?x*y%mod:x*y;}
struct node{int to,w;};
vector<node> G[N];
int dep[N],fa[N],son[N],sz[N],ed[N],ned[N],id[N],bel[N],cnt;
il void dfs1(int x,int ff){
	dep[x]=dep[ff]+1;
	fa[x]=ff,sz[x]=1;
	int mx=-1,to,w,len=SZ(G[x]);
	node tp;
	for(int i=0;i<len;++i){
		tp=G[x][i],to=tp.to,w=tp.w;
		if(to==ff) continue;
		ed[to]=w;
		dfs1(to,x);
		sz[x]+=sz[to];
		if(sz[to]>mx) son[x]=to,mx=sz[to];
	}
} 
il void dfs2(int x,int topx){
	id[x]=++cnt,ned[cnt]=ed[x];
	bel[x]=topx;
	if(!son[x]) return;
	dfs2(son[x],topx);
	int to,len=SZ(G[x]);
	node tp;
	for(int i=0;i<len;++i){
		tp=G[x][i],to=tp.to;
		if(to==son[x] || to==fa[x]) continue;
		dfs2(to,to);
	}
} 
int n,m,b[N],tot=0,rt[N*20],ls[N*20],rs[N*20],s[N*20],all=0;
il void build(int &rt,int l,int r){
	rt=++tot,s[rt]=0;
	if(l==r) return;
	build(ls[rt],l,mid),build(rs[rt],mid+1,r);
} 
il void update(int &rt,int l,int r,int last,int p){
	rt=++tot,ls[rt]=ls[last],rs[rt]=rs[last];
	s[rt]=s[last]+1;
	if(l==r) return;
	if(p<=mid) update(ls[rt],l,mid,ls[last],p);
	else update(rs[rt],mid+1,r,rs[last],p);
}
il int query(int ss,int ee,int l,int r,int k){
	if(l==r) return s[ee]-s[ss];
	if(k>mid) return s[ls[ee]]-s[ls[ss]]+query(rs[ss],rs[ee],mid+1,r,k);
	else if(k==mid) return s[ls[ee]]-s[ls[ss]];
	else return query(ls[ss],ls[ee],l,mid,k);	
}
il int r_query(int x,int y,int k){
//	cout<<"r_query "<<x<<" "<<y<<" "<<k<<endl;
//	cout<<bel[x]<<" "<<bel[y]<<endl;
	int res=0;
	while(bel[x]!=bel[y]){
		if(dep[bel[x]]<dep[bel[y]]) swap(x,y);
		res+=query(rt[id[bel[x]]-1],rt[id[x]],1,all,k);
		x=fa[bel[x]];
	}
	if(dep[x]>dep[y]) swap(x,y);
	res+=query(rt[id[x]],rt[id[y]],1,all,k);
	return res;
}
struct Q{
	int l,r,k;
}qu[N];
int main(){
//	std::ios::sync_with_stdio(0);cin.tie(0);
	read(n),read(m);
	int x,y,w,tt=0;
	for(int i=1;i<=n-1;++i){
		read(x),read(y),read(w);
		G[x].pb({y,w});
		G[y].pb({x,w});
		b[++tt]=w;
	}
	for(int i=1;i<=m;++i){
		read(x),read(y),read(w);
		qu[i]={x,y,w};
		b[++tt]=w;
	}
	dfs1(1,0),dfs2(1,1);
	b[++tt]=0;
	sort(b+1,b+tt+1);
	all=unique(b+1,b+tt+1)-(b+1);
	build(rt[0],1,all);
	for(int i=1;i<=n;++i){
		ned[i]=lower_bound(b+1,b+all+1,ned[i])-b;
		update(rt[i],1,all,rt[i-1],ned[i]);
	}
	for(int i=1;i<=m;++i){
		qu[i].k=lower_bound(b+1,b+all+1,qu[i].k)-b;
		printf("%d\n",r_query(qu[i].l,qu[i].r,qu[i].k));
	}
	return 0;
}








 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值