CF 1076E Vasya and a Tree(线段树+树剖)

传送门

解题思路

  首先按照每个修改时(x)的深度(+d)从大到小排序,然后按照深度分层,一层一层的修改,修改的时候就直接暴力修改子树,然后每做完一层把答案都取下来,因为以后的所有修改的深度都小于当前层,也就是无法对当前层的节点造成贡献。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>

using namespace std;
const int MAXN = 300005;
typedef long long LL;

inline int rd(){
	int x=0,f=1;char ch=getchar();
	while(!isdigit(ch)) f=ch=='-'?0:1,ch=getchar();
	while(isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
	return f?x:-x;
}

void out(LL x){
	if(!x) return;
	out(x/10);putchar('0'+x%10);
}	

inline void OUT(LL x){
	if(!x) putchar('0');
	else out(x);
	putchar(' ');
}

int n,m,head[MAXN],cnt,to[MAXN<<1],nxt[MAXN<<1],Max;
int dep[MAXN],fa[MAXN],son[MAXN],siz[MAXN],id[MAXN],top[MAXN],num;
LL sum[MAXN<<2],tag[MAXN<<2],ans[MAXN];
vector<int> a[MAXN];

struct Query{
	int v,d,rt;
	friend bool operator<(const Query A,const Query B){
		return A.d>B.d;
	}
}q[MAXN];

inline int max(int x,int y){
	return x>y?x:y;
}

inline int min(int x,int y){
	return x<y?x:y;
}

inline void add(int bg,int ed){
	to[++cnt]=ed,nxt[cnt]=head[bg],head[bg]=cnt;
}

void dfs1(int x,int f,int d){
	dep[x]=d;fa[x]=f;siz[x]=1;Max=max(Max,d);a[d].push_back(x);
	int maxson=-1,u;
	for(int i=head[x];i;i=nxt[i]){
		u=to[i];if(u==f) continue;
		dfs1(u,x,d+1);siz[x]+=siz[u];
		if(siz[u]>maxson) maxson=siz[u],son[x]=u;
	}
}

void dfs2(int x,int topf){
	top[x]=topf;id[x]=++num;int u;
	if(!son[x]) return;dfs2(son[x],topf);
	for(int i=head[x];i;i=nxt[i]){
		u=to[i];if(u==fa[x] || u==son[x]) continue;
		dfs2(u,u);
	}
}

inline void pushdown(int x,int ln,int rn){
	tag[x<<1]+=tag[x];tag[x<<1|1]+=tag[x];
	sum[x<<1]+=tag[x]*ln;sum[x<<1|1]+=tag[x]*rn;
	tag[x]=0;
}

void update(int x,int l,int r,int L,int R,int k){
	if(L<=l && r<=R){
		sum[x]+=(LL)(r-l+1)*k;
		tag[x]+=k;return ;
	}
	int mid=(l+r)>>1;if(tag[x]) pushdown(x,mid-l+1,r-mid);
	if(mid>=L) update(x<<1,l,mid,L,R,k);
	if(mid<R) update(x<<1|1,mid+1,r,L,R,k);
	sum[x]=sum[x<<1]+sum[x<<1|1];
}

LL query(int x,int l,int r,int L){
	if(l==r) return sum[x];
	int mid=(l+r)>>1;LL ret=0;if(tag[x]) pushdown(x,mid-l+1,r-mid);
	if(L<=mid) return query(x<<1,l,mid,L);
	else return query(x<<1|1,mid+1,r,L);
}

int main(){
	n=rd();int x,y,z;
	for(int i=1;i<n;i++){
		x=rd(),y=rd();
		add(x,y),add(y,x);
	}
	dfs1(1,0,1);dfs2(1,1);m=rd();
	for(int i=1;i<=m;i++){	
		x=rd(),y=rd(),z=rd();
		q[i].rt=x;q[i].d=min(dep[x]+y,Max);q[i].v=z;
	}
	sort(q+1,q+1+m);
	for(int i=1;i<=m;i++){
		x=q[i].rt,y=q[i].d,z=q[i].v;
		if(y!=q[i-1].d)
			for(int j=q[i-1].d;j>y;j--)
				for(int k=0;k<a[j].size();k++)
					ans[a[j][k]]=query(1,1,n,id[a[j][k]]);
		update(1,1,n,id[x],id[x]+siz[x]-1,z);
	}
	for(int i=q[m].d;i;i--)
		for(int j=0;j<a[i].size();j++)
			ans[a[i][j]]=query(1,1,n,id[a[i][j]]);
	for(int i=1;i<=n;i++) OUT(ans[i]);
	return 0;
}
原文地址:https://www.cnblogs.com/sdfzsyq/p/10065496.html