abc187 --E-Through Path (difference on the tree) / tree chain division + line segment tree

Title description:

Give you the initial weight of each point of a tree with 0
N-1 edges, each edge connects a[i]-b[i]
and then gives you q operations (two types)

  1. Take a[i] as the starting point to traverse all points and the path cannot pass b[i], add w to all points on the path

  2. Take b[i] as the starting point to traverse all points and the path cannot pass a[i], add w to all points on the path

Question idea (solution 1):

The two operations are essentially the same, but the starting point is different.
If the starting point is u, the point that cannot be passed is v.
If dep[u] <dep[v] is to add w to all points except the subtree of v.
If dep[u]> dep[v] just add w to the subtree of u

Specific operation:

First preprocess the depth of each node.
Assuming that the root node is 1,
then for dep[u] <dep[v] , we add w to the entire tree to be num[1]+=w, and then subtract num[v] Go to w
for dep[u] >dep[v] num[u]+=w

CODE:

ll  n,q,fa[maxn],num[maxn],a[maxn],b[maxn],ans[maxn],dep[maxn];
vector<ll>e[maxn];
void pre_work(int u,int p) {
    
    
	fa[u] = p ,	dep[u] = dep[p]+1;
	for(int v:e[u]) if(v!=p) pre_work(v,u);
}
void dfs(int  u,int  p,ll  s) {
    
    
	s+=num[u];
	ans[u] = s;
	for(int v:e[u]) {
    
    
		if(v==p) continue;
		dfs(v,u,s);
	}
}
int main() {
    
    
	n=read();
	for(int i=1 ; i<=n-1 ; i++) {
    
    
		int u = read();
		int v = read();
		a[i]=u,b[i]=v;
		e[u].push_back(v);
		e[v].push_back(u);
	}
	pre_work(1,0);
	q=read();
	while(q--) {
    
    
		int t = read();
		int id = read(),u,v;
		ll w = read();
		u=a[id],v=b[id];
		if(t==2) swap(u,v);
		if(dep[u]>dep[v]) num[u]+=w;
		else num[1]+=w,num[v]-=w;
	}
	dfs(1,0,0);
	rep(i,1,n) printf("%lld\n",ans[i]);
	return 0;
}

(solution 2)

You can also use the line segment tree after the dfs sequence. You can also use the line segment tree
after the tree section. Practice the tree section. The code is smelly and long.
After the sequence is converted, the interval is modified, and the single-point query
CODE:

ll  n,q,fa[maxn],a[maxn],b[maxn],dep[maxn];
ll son[maxn],size_s[maxn],top[maxn],id[maxn],idex,od[maxn];
vector<ll>e[maxn];
struct node {
    
    
	ll l,r,lz,sum;
} num[maxn*4];
void pre_work(int u,int p) {
    
    
	fa[u] = p,dep[u] = dep[p]+1;
	size_s[u] = 1;
	for(int v:e[u]) {
    
    
		if(v==p) continue;
		pre_work(v,u);
		size_s[u]+=size_s[v];
		if(son[u]==0||size_s[son[u]]<size_s[v]) son[u] = v;
	}
}

void work(int u,int top_v) {
    
    
	id[u] = ++idex;
	od[idex] = u;
	top[u] = top_v;
	if(son[u]==0) return ;
	work(son[u],top_v);
	for(int v:e[u]) {
    
    
		if(v==fa[u]||v==son[u]) continue;
		work(v,v);
	}
}
void push_up(int st) {
    
    
	num[st].sum = num[st*2].sum + num[st*2+1].sum;
}
void push_down(int st) {
    
    
	if(num[st].lz==0) return ;
	num[st*2].lz+=num[st].lz;
	num[st*2+1].lz+=num[st].lz;

	num[st*2].sum += (num[st*2].r - num[st*2].l+1)*num[st].lz;
	num[st*2+1].sum += (num[st*2+1].r - num[st*2+1].l+1)*num[st].lz;
	num[st].lz =0 ;
}
void build(int st,int l,int r) {
    
    
	num[st].l = l,num[st].r = r;
	if(l==r) {
    
    
		num[st].lz=	num[st].sum =0 ;
		return ;
	}
	int mid = (l+r)>>1;
	build(st*2,l,mid);
	build(st*2+1,mid+1,r);
	push_up(st);
}
void update(int st,int l,int r,int ql,int qr,ll w) {
    
    
	if(ql<=l&&qr>=r) {
    
    
		num[st].lz+=w;
		num[st].sum += (num[st].r-num[st].l+1)*w*1ll;
		return ;
	}
	int mid = (l+r)>>1;
	if(ql<=mid) update(st*2,l,mid,ql,qr,w);
	if(qr>mid) update(st*2+1,mid+1,r,ql,qr,w);
	push_up(st);
}
ll query(int st,int l,int r,int pos) {
    
    
	if(l==r) {
    
    
		return num[st].sum;
	}
	push_down(st);
	int mid = (l+r)>>1;
	if(pos<=mid) return query(st*2,l,mid,pos);
	else return query(st*2+1,mid+1,r,pos);
	push_up(st);
}
int main() {
    
    
	n=read();
	for(int i=1 ; i<=n-1 ; i++) {
    
    
		int u = read();
		int v = read();
		a[i]=u,b[i]=v;
		e[u].push_back(v);
		e[v].push_back(u);
	}
	pre_work(1,0);
	work(1,1);
	build(1,1,n);
	q=read();
	while(q--) {
    
    
		int t = read();
		int ei = read(),u,v;
		ll w = read();
		u=a[ei],v=b[ei];
		if(t==2) swap(u,v);
		if(dep[u]>dep[v]) {
    
    
			update(1,1,n,id[u],id[u]+size_s[u]-1,w);
		} else {
    
    
			update(1,1,n,id[v],id[v]+size_s[v]-1,-w);
			update(1,1,n,id[1],id[1]+size_s[1]-1,w);
		}
	}
	rep(i,1,n) printf("%lld\n",query(1,1,n,id[i]));

	return 0;
}

Insert picture description here

Guess you like

Origin blog.csdn.net/wmy0536/article/details/112150106