社区讨论

Wa on4求助大佬

CF916EJamie and Tree参与者 1已保存回复 1

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
1 条
当前快照
1 份
快照标识符
@m32h5vf4
此快照首次捕获于
2024/11/04 11:41
去年
此快照最后确认于
2024/11/04 14:19
去年
查看原帖
CPP
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e5+5;
int n,m;
int d[N],f[N][18],dfn[N],depth[N],tot;
vector<int> g[N];
ll val[N],ans;
int e[N],s[N];
int root=1;
struct node{
	ll ans,tag;
	int l,r;
}rt[N];
void build(int l,int r,int k){
	rt[k].l=l,rt[k].r=r,rt[k].tag=rt[k].ans=0;
	if(l==r){rt[k].ans=val[dfn[l]];return;}
	int mid=(l+r)>>1;
	build(l,mid,k<<1),build(mid+1,r,k<<1|1);
	rt[k].ans=rt[k<<1].ans +rt[k<<1|1].ans;
}
void down(int k){
	rt[k<<1].tag +=rt[k].tag;rt[k<<1|1].tag +=rt[k].tag;
	rt[k<<1].ans +=(ll)(rt[k<<1].r-rt[k<<1].l+1)*rt[k].tag;
	rt[k<<1|1].ans +=(ll)(rt[k<<1|1].r-rt[k<<1|1].l+1)*rt[k].tag;
	rt[k].tag=0;
}
void update(int l,int r,int k,ll val){
	if(l<=rt[k].l && rt[k].r<=r){
		rt[k].tag +=val;
		rt[k].ans +=(ll)(rt[k].r-rt[k].l+1)*val;
		return;
	}
	if(rt[k].tag)down(k);
	if(r>=rt[k<<1|1].l)update(l,r,k<<1|1,val);
	if(l<=rt[k<<1].r)update(l,r,k<<1,val);
	rt[k].ans=rt[k<<1].ans+rt[k<<1|1].ans;
}
ll quer(int l,int r,int k){
	if(l<=rt[k].l && rt[k].r<=r){return rt[k].ans;}
	if(rt[k].tag)down(k);
	ll tans=0;
	if(r>=rt[k<<1|1].l)tans+=quer(l,r,k<<1|1);
	if(l<=rt[k<<1].r)tans+=quer(l,r,k<<1);
	return tans;
}
void dfs(int u,int lst){
	tot++;dfn[tot]=u;
	s[u]=tot;
	depth[u]=depth[lst]+1;
	f[u][0]=lst;
	for(int i=17;i>=1;i--)f[u][i]=f[f[u][i-1]][i-1];
	for(int i=0;i<g[u].size();i++){
		int v=g[u][i];
		if(v==lst)continue;
		dfs(v,u);
	}
	e[u]=tot;
}
inline int lca(int u,int v){
	if(depth[u]<depth[v])swap(u,v);
	for(int i=17;i>=0;i--)if(depth[f[u][i]]>=depth[v])u=f[u][i];
	for(int i=17;i>=0;i--)if(depth[f[u][i]]!=depth[f[v][i]])u=f[u][i],v=f[v][i];
	if(u==v)return u;
	else return f[u][0];
}
inline int dis(int u,int v){
	return depth[u]+depth[v]-2*depth[lca(u,v)];
}
inline int jum(int u,int bd){
	for(int i=17;i>=0;i--)if(depth[f[u][i]]>=bd)u=f[u][i];
	return u;
}
int main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++)cin>>val[i];
	for(int i=1;i<n;i++){
		int u,v;
		cin>>u>>v;
		g[u].push_back(v);
		g[v].push_back(u);  
	}
	dfs(1,0);
	build(1,tot,1);
	while(m--){
		int opt,u,v;
		ll x;
		cin>>opt;
		if(opt==1){
			cin>>u;
			root=u;
		}
		if(opt==2){
			cin>>u>>v>>x;
			int lcaa=lca(u,v);
			int td=(dis(root,u)+dis(root,v)-dis(u,v))/2;
			if(!td)update(s[1],e[1],1,x);
			else if(lca(lcaa,root)==lcaa){
				
				u=jum(root,depth[root]-td+1);
				//printf("all add%d  qv %d\n",1,u);
				
				update(s[1],e[1],1,x);
				update(s[u],e[u],1,-x);
			}else update(s[lcaa],e[lcaa],1,x);
		}
		if(opt==3){
			cin>>u;
			int lcaa=lca(root,u);
			if(root==u)cout<<quer(s[1],e[1],1)<<"\n";
			else
			if(lcaa==u){
				u=jum(root,depth[lcaa]+1);
			//	printf(" all %d qv %d\n",1,u);
				cout<<quer(s[1],e[1],1)-quer(s[u],e[u],1)<<"\n";
			}
			else cout<<quer(s[u],e[u],1)<<"\n";
		}
	}
	return 0;
} 
做法是和第一篇题解一样的,先拍扁树,然后根据 root 和要修改的子树的相对位置来分类讨论

回复

1 条回复,欢迎继续交流。

正在加载回复...