线段树合并65pts求助
查看原帖
线段树合并65pts求助
989792
lrx___楼主2025/1/23 21:23
#include <bits/stdc++.h>
#ifndef ONLINE_JUDGE
#define debug(...) fprintf(stderr,__VA_ARGS__)
#else
#define debug(...)
#endif
using namespace std;
using namespace chrono;
typedef signed char i8;typedef short i16;typedef int i32;typedef long long i64;typedef unsigned char u8;typedef unsigned short u16;typedef unsigned u32;typedef unsigned long long u64;typedef float f32;typedef double f64;typedef long double f96;

constexpr int N(3e5+5);
int n,m,sta[N<<5],top,w[N],ans[N],dep[N],fa[19][N],add1[N],root[N];
vector<int> g[N],add2[N],del1[N],del2[N];
struct node{
	int ls,rs,val;
}t[N<<5];
namespace segment_tree{
	void update(int x,int k,int& u,int l=1,int r=n){
		if(!u){
			u=sta[--top];
			t[u].ls=t[u].rs=0;
			t[u].val=0;
		}
		if(l==r){
			t[u].val+=k;
			return;
		}
		const int mid{(l+r)>>1};
		x<=mid?update(x,k,t[u].ls,l,mid):update(x,k,t[u].rs,mid+1,r);
	}
	void merge_tree(int& u,int& v,int l=1,int r=n){
		if(!u){
			u=v;v=0;return;
		}
		if(!v){
			return;
		}
		if(l==r){
			t[u].val+=t[v].val;
		}else{
			const int mid{(l+r)>>1};
			merge_tree(t[u].ls,t[v].ls,l,mid);
			merge_tree(t[u].rs,t[v].rs,mid+1,r);
		}
		sta[top++]=v;v=0;
	}
	int query(int x,int& u,int l=1,int r=n){
		if(l==r){
			return t[u].val;
		}
		const int mid{(l+r)>>1};
		return x<=mid?query(x,t[u].ls,l,mid):query(x,t[u].rs,mid+1,r);
	}
}
namespace tree{
	void dfs(int u,int father){
		int i;
		dep[u]=dep[(*fa)[u]=father]+1;
		for(i=1;i<19;++i){
			fa[i][u]=fa[i-1][fa[i-1][u]];
		}
		for(auto& v:g[u]){
			if(v!=father){
				dfs(v,u);
			}
		}
	}
	void dfs1(int u,int father){
		int fir{dep[u]};
		for(auto& v:g[u]){
			if(v!=father){
				dfs1(v,u);
				segment_tree::merge_tree(root[u],root[v]);
			}
		}
		segment_tree::update(fir,add1[u],root[u]);
		for(auto& va:del1[u]){
			segment_tree::update((fir+va-1)%n+1,-1,root[u]);
		}
		ans[u]+=segment_tree::query((fir+w[u]-1)%n+1,root[u]);
	}
	void dfs2(int u,int father){
		int fir{n-dep[u]+1};
		for(auto& v:g[u]){
			if(v!=father){
				dfs2(v,u);
				segment_tree::merge_tree(root[u],root[v]);
			}
		}
		for(auto& va:add2[u]){
			segment_tree::update((fir+va-1)%n+1,1,root[u]);
		}
		for(auto& va:del2[u]){
			segment_tree::update((fir+va-1)%n+1,-1,root[u]);
		}
		ans[u]+=segment_tree::query((fir+w[u]-1)%n+1,root[u]);
	}
}
int get_lca(int u,int v){
	int i;
	if(dep[u]<dep[v]){
		swap(u,v);
	}
	for(i=18;~i;--i){
		if(dep[fa[i][u]]>=dep[v]){
			u=fa[i][u];
		}
	}
	if(u==v){
		return u;
	}
	for(i=18;~i;--i){
		if(fa[i][u]!=fa[i][v]){
			u=fa[i][u];v=fa[i][v];
		}
	}
	return (*fa)[u];
}
void reset_node(){
	iota(sta,sta+(N<<5)-1,1);
	top=(N<<5)-1;
	memset(root+1,0,n<<2);
}
int main(){
	int i,u,v,l;
	scanf("%d%d",&n,&m);
	for(i=1;i<n;++i){
		scanf("%d%d",&u,&v);
		g[u].push_back(v);
		g[v].push_back(u);
	}
	tree::dfs(1,0);
	for(i=1;i<=n;++i){
		scanf("%d",w+i);
	}
	for(i=1;i<=m;++i){
		scanf("%d%d",&u,&v);
		l=get_lca(u,v);
		++add1[u];
		add2[v].push_back(dep[u]+dep[v]-(dep[l]<<1));
		del1[l].push_back(dep[u]-dep[l]);
		if((*fa)[l]){
			del2[(*fa)[l]].push_back(dep[u]-dep[l]-1);
		}
	}
	reset_node();
	tree::dfs1(1,0);
	reset_node();
	tree::dfs2(1,0);
	for(i=1;i<=n;++i){
		printf("%d ",ans[i]);
	}
	return 0;
}
2025/1/23 21:23
加载中...