一眼dsu on tree模板题(
查看原帖
一眼dsu on tree模板题(
741839
arrowpoint楼主2024/5/24 23:55

之前才学会dsu on tree这种奇怪的算法,没想到现在就能用上(

代码有点复杂,但好处是根本不用动脑,套3步公式(遍历轻儿子,遍历重儿子,计算轻儿子)就可以直接AC

建议标签加上dsu on tree

(话说好像大部分能用dsu on tree的题都没有加这个标签

#include<bits/stdc++.h>
#define int long long
#define endl '\n'
#define lowbit(x) x & -x
using namespace std;

const int N = 1e5+10;
int n,m;
vector<int> vec[N];
int hson[N],sz[N];
int c[N]; 
int ans[N];
int HH;
struct node{
	int id,num;
}a[N],b[N];
inline bool cmp(node x,node y){
	return x.num<y.num;
}

inline void add(int x,int val){
	while(x<=n){
		c[x] += val;
		x += lowbit(x);
	}
}
inline int query(int x){
	int res = 0;
	while(x){
		res += c[x];
		x -= lowbit(x);
	}
	return res;
}

inline void dfs(int x,int fa){
	sz[x] = 1;
	for(int i=0;i<vec[x].size();i++){
		int v = vec[x][i];
		if(v==fa) continue;
		dfs(v,x);
		sz[x] += sz[v];
		if(sz[v] > sz[hson[x]]){
			hson[x] = v;
		}
	}
}

inline void calc(int x,int fa,int val){
	add(a[x].num,val);
	for(int i=0;i<vec[x].size();i++){
		int v = vec[x][i];
		if(v==fa || v==HH) continue;
		calc(v,x,val);
	}
}

inline void dsu(int x,int fa,int op){
	for(int i=0;i<vec[x].size();i++){
		int v = vec[x][i];
		if(v==fa || v==hson[x]) continue;
		dsu(v,x,0);
	}
	if(hson[x]){
		dsu(hson[x],x,1);
		HH = hson[x];
	}
	calc(x,fa,1);
	ans[x] = sz[x]-query(a[x].num);
	HH = 0;
	if(!op){
		calc(x,fa,-1);
	}
}

signed main(){
	ios::sync_with_stdio(false);
	cin>>n;
	int q1;
	for(int i=1;i<=n;i++){
		cin>>a[i].num;
		a[i].id = i;
		b[i] = {i,a[i].num};
	}
	sort(b+1,b+n+1,cmp);
	for(int i=1;i<=n;i++){
		a[b[i].id].num = i;
	}
	for(int i=2;i<=n;i++){
		cin>>q1;
		vec[q1].push_back(i);
		vec[i].push_back(q1);
	}
	dfs(1,0);
	dsu(1,0,0);
	for(int i=1;i<=n;i++){
		cout<<ans[i]<<endl;
	}
	
	return 0;
}
2024/5/24 23:55
加载中...