长链剖分模板

该代码实现了一个特殊的DSU(DisjointSetUnion)结构,其中每个节点可以共享数据结构。在树形数据中,通过DFS遍历处理子树,更新节点信息,并用于解决特定的图问题。程序接收边的输入构造树,然后进行两遍DFS,最后执行DSU操作并输出结果。
摘要由CSDN通过智能技术生成
  • 大概就是dsu on tree的一种特殊情况 是on的
  • 每个结点可以公用数据结构
#include <bits/stdc++.h>
using namespace  std;
#define  int long long
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef vector<int> vi;
#define fi first
#define se second
#define pb  push_back
#define inf 1ll<<62
#define db double
#define endl "\n"
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define de_bug(x) cerr << #x << "=" << x << endl
#define all(a) a.begin(),a.end()
#define IOS   std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define  fer(i,a,b)  for(int i=a;i<=b;i++)
#define  der(i,a,b)  for(int i=a;i>=b;i--)
mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());
const int mod = 1e9 + 7;
const int N = 1e6 + 10;
int n, m , k;
vi g[N];
int son[N];
int len[N];
int l[N],r[N];
vector<pii>q[N];
int f[N];
int ans[N];
int idx;
int s[N];
int a[N];

void dfs(int u,int fa) {
	f[u]=fa;
	for(auto v:g[u]) {
		if(v!=fa) {
			dfs(v,u);
			if(!son[u]||len[son[u]]<len[v])son[u]=v;
		}
	}
	len[u]=len[son[u]]+1;
}
void dfs2(int x) {
	l[x]=++idx;
	r[x]=l[x]+len[x]-1;
	if(son[x])dfs2(son[x]);
	for(auto v:g[x]) {
		if(v!=f[x]&&v!=son[x]) {
			dfs2(v);
		}
	}
}
void dsu(int u) {
	if(son[u]) {
		dsu(son[u]);
	}
	for(auto v:g[u]) {
		if(v!=f[u]&&v!=son[u]) {
			dsu(v);
			for(int x=l[v],k=1; x<=r[v]; x++,++k) {
				s[l[u]+k]+=s[x];
			}
		}
	}
	s[l[u]]+=a[u];
	for(auto & it:q[u]) {
		ans[it.fi]+=s[l[u]+it.se];
	}
}
void solve() {
	cin>>n;
	fer(i,1,n)cin>>a[i];
	fer(i,1,n-1) {
		int a,b;
		cin>>a>>b;
		g[a].push_back(b);
		g[b].push_back(a);
	}
	dfs(1,0);
	dfs2(1);
	cin>>m;
	fer(i,1,m) {
		int a,b;
		cin>>a>>b;
		q[a].push_back({i,b});
	}
	dsu(1);
	fer(i,1,m) {
		cout<<ans[i]<<endl;
	}
}


signed main() {
	IOS;
	int _ = 1;
	//cin>>_;
	while( _-- )
		solve();
	return 0;
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值