[CF494D] Birthday 题解

首先 \(S(u)\) 显然是 \(u\) 的子树。

假如 \(u\) 是定点,问题转化为区间求平方和,十分简单。

于是我们用线段树维护区间平方和,支持区间加,然后离线问题,在 \(u\) 的位置处理即可。线段树从 \(fa\) 转移到 \(u\) 是极度简单的。

时间复杂度 \(O(n\log n)\)

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+5,M=4e5+5,p=1e9+7;
int n,q,dfn[N],low[N],sm[M],pw[M],ad[M],as[N];
vector<int>g[N],w[N],qu[N],nm[N];int id,dis[N];
void push_up(int x){
	sm[x]=(sm[x*2]+sm[x*2+1])%p;
	pw[x]=(pw[x*2]+pw[x*2+1])%p;
}void down(int x,int a,int len){
	pw[x]=(pw[x]+sm[x]*a*2+len*a%p*a)%p;
	sm[x]=(sm[x]+len*a)%p,ad[x]=(ad[x]+a)%p;
}void push_down(int x,int ln,int rn){
	down(x*2+1,ad[x],rn);
	down(x*2,ad[x],ln),ad[x]=0;
}void add(int x,int l,int r,int L,int R,int v){
	if(L<=l&&r<=R)
		return down(x,v,r-l+1);
	int mid=(l+r)/2;
	push_down(x,mid-l+1,r-mid);
	if(L<=mid) add(x*2,l,mid,L,R,v);
	if(R>mid) add(x*2+1,mid+1,r,L,R,v);
	push_up(x);
}int sum(int x,int l,int r,int L,int R){
	if(L<=l&&r<=R) return pw[x];
	int mid=(l+r)/2,re=0;
	push_down(x,mid-l+1,r-mid);
	if(R>mid) re=sum(x*2+1,mid+1,r,L,R);
	if(L<=mid) re+=sum(x*2,l,mid,L,R);
	return re;
}void dfs1(int x,int fa){
	dfn[x]=++id;
	add(1,1,n,id,id,dis[x]);
	for(int i=0;i<g[x].size();i++){
		int y=g[x][i],c=w[x][i];
		if(y==fa) continue;
		dis[y]=(dis[x]+c)%p,dfs1(y,x);
	}low[x]=id;
}void dfs2(int x,int fa){
	for(int i=0;i<g[x].size();i++){
		int y=g[x][i],c=w[x][i];
		if(y==fa) continue;
		add(1,1,n,dfn[y],low[y],-c-c);
		add(1,1,n,1,n,c),dfs2(y,x);
		add(1,1,n,dfn[y],low[y],c+c);
		add(1,1,n,1,n,-c);
	}for(int i=0;i<qu[x].size();i++)
		as[nm[x][i]]=2*sum(1,1,n,dfn[qu[x][i]],low[qu[x][i]])-pw[1];
}signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	cin>>n;
	for(int i=1;i<n;i++){
		int x,y,z;cin>>x>>y>>z;
		g[x].push_back(y),g[y].push_back(x);
		w[x].push_back(z),w[y].push_back(z);
	}cin>>q,dfs1(1,0);
	for(int i=1;i<=q;i++){
		int x,y;cin>>x>>y;
		qu[x].push_back(y);
		nm[x].push_back(i);
	}dfs2(1,0);
	for(int i=1;i<=q;i++)
		cout<<(as[i]%p+p)%p<<"\n";
	return 0;
}
posted @ 2024-12-20 11:01  white_tiger  阅读(17)  评论(0)    收藏  举报