loj147,MLE60pts,空间求卡常
  • 板块学术版
  • 楼主toolong114514
  • 当前回复0
  • 已保存回复0
  • 发布时间2024/1/20 16:55
  • 上次更新2024/1/20 19:31:53
查看原帖
loj147,MLE60pts,空间求卡常
477821
toolong114514楼主2024/1/20 16:55
#include<iostream>
#include<cstring>
using namespace std;
#define int long long
const int N=1e6+10;
struct node{
	signed to,nxt;
}edge[2*N];
signed head[N];
signed cnt;
inline void add(signed u,signed v){
	edge[++cnt]={v,head[u]};
	head[u]=cnt;
}
signed in[N],out[N],dep[N],inv[2*N];
int vv[N];
bool knd[2*N];
int st[N][30];
int t;
void dfs(int x,int last){
	st[x][0]=last;
	in[x]=++t;
	dep[x]=dep[last]+1;
	inv[t]=vv[x];
	for(int i=head[x];i!=-1;i=edge[i].nxt){
		if(edge[i].to!=last) dfs(edge[i].to,x);
	}
	out[x]=++t;
	knd[t]=true;
	inv[t]=-vv[x];
}
struct ccf{
	signed l,r,pcnt,ncnt;
	int sum,laz;
	//pcnt:正的计数 ncnt:负的计数 
}tree[4*N];
void build(signed pos,signed lft,signed rgt){
	tree[pos].l=lft;
	tree[pos].r=rgt;
	if(lft==rgt){
		tree[pos].sum=inv[lft];
		if(!knd[lft]){//正 
			tree[pos].pcnt=1;
		}else{
			tree[pos].ncnt=1;
		}
		return;
	}
	signed mid=(lft+rgt)/2;
	build(pos*2,lft,mid);
	build(pos*2+1,mid+1,rgt);
	tree[pos].sum=tree[pos*2].sum+tree[pos*2+1].sum;
	tree[pos].pcnt=tree[pos*2].pcnt+tree[pos*2+1].pcnt;
	tree[pos].ncnt=tree[pos*2].ncnt+tree[pos*2+1].ncnt;
}
void push_down(int pos){
	tree[pos*2].sum+=tree[pos*2].pcnt*tree[pos].laz-tree[pos*2].ncnt*tree[pos].laz;
	tree[pos*2+1].sum+=tree[pos*2+1].pcnt*tree[pos].laz-tree[pos*2+1].ncnt*tree[pos].laz;
	tree[pos*2].laz+=tree[pos].laz;
	tree[pos*2+1].laz+=tree[pos].laz;
	tree[pos].laz=0;
}
void upd(signed pos,signed lft,signed rgt,signed x){
	if(lft<=tree[pos].l&&tree[pos].r<=rgt){
		tree[pos].sum+=tree[pos].pcnt*x-tree[pos].ncnt*x;
		tree[pos].laz+=x;
		return;
	}
	if(rgt<tree[pos].l||tree[pos].r<lft) return;
	push_down(pos);
	upd(pos*2,lft,rgt,x);
	upd(pos*2+1,lft,rgt,x);
	tree[pos].sum=tree[pos*2].sum+tree[pos*2+1].sum;
}
int ask(signed pos,signed lft,signed rgt){
	if(lft<=tree[pos].l&&tree[pos].r<=rgt) return tree[pos].sum;
	if(rgt<tree[pos].l||tree[pos].r<lft) return 0;
	push_down(pos);
	return ask(pos*2,lft,rgt)+ask(pos*2+1,lft,rgt);
}
int lca(signed x,signed y){
	if(dep[x]<dep[y]) swap(x,y);
	for(signed i=25;i>=0;i--){
		if((1<<i)<=dep[x]-dep[y]) x=st[x][i];
	}
	if(x==y) return x;
	for(signed i=25;i>=0;i--){
		if((1<<i)<=dep[x]&&st[x][i]!=st[y][i]){
			x=st[x][i];
			y=st[y][i];
		}
	}
	return st[x][0];
}
int n,m,r;
signed main(){
	ios::sync_with_stdio(false);
	memset(head,-1,sizeof(head));
	cin>>n>>m>>r;
	for(signed i=1;i<=n;i++){
		cin>>vv[i];
	}
	for(signed i=1;i<n;i++){
		int x,y;
		cin>>x>>y;
		add(x,y);
		add(y,x);
	}
	dfs(r,0);
	for(signed j=1;j<=26;j++){
		for(signed i=1;i<=n;i++){
			st[i][j]=st[st[i][j-1]][j-1];
		}
	}
	build(1,1,2*n);
	while(m--){
		signed op,a,b;
		cin>>op>>a>>b;
		if(op==1){
			upd(1,in[a],in[a],b);
			upd(1,out[a],out[a],b);
		}else if(op==2){
			upd(1,in[a],out[a],b);
		}else{
			signed tmp=lca(a,b);
			cout<<ask(1,in[tmp],in[a])+ask(1,in[tmp],in[b])-ask(1,in[tmp],in[tmp])<<'\n';
		}
	}
	return 0;
}
2024/1/20 16:55
加载中...