萌新求助树链剖分
查看原帖
萌新求助树链剖分
307535
Custlo0793楼主2021/5/26 14:00
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#define N 400001
#define aut(u) for(int i=first[u];i;i=nxt[i])
using namespace std;
typedef long long ll;
int first[N],nxt[N],to[N],top,p,n,m,rt;
int dfn[N],dep[N],size[N],fa[N],son[N],val[N],link[N],cnt;
inline int rd(){
    int x=0;char c=getchar();
    while(c>'9'||c<'0')c=getchar();
    while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();
    return x;
}
inline void add(int x,int y) {
	nxt[++top]=first[x];
	to[top]=y;
	first[x]=top;
	return ;
}
namespace segment{
  ll sum[N*4],up[N*4];
  ll lef(ll x) {return x<<1;}
  ll rig(ll x) {return x<<1|1;}
  void pushup(ll now) {
    sum[now]=sum[lef(now)]+sum[rig(now)];
  }
  void build(ll now,ll l,ll r){
	  up[now]=0;
	  if(l==r){
	      sum[now]=val[dfn[l]];
		  return ;
	  }
	  ll mid=(l+r)>>1;
	  build(lef(now),l,mid);
      build(rig(now),mid+1,r);	
	  pushup(now);
  }
  void f(ll now,ll l,ll r,ll k){
      up[now]+=k;
	  sum[now]+=k*(r-l+1);
  }
  void pushdown(ll now,ll l,ll r){
	  ll mid=(l+r)>>1;
	  f(lef(now),l,mid,up[now]);
	  f(rig(now),mid+1,r,up[now]);
	  up[now]=0;
  }
  void update(ll dl,ll dr,ll l,ll r,ll now,ll k){
	  if(dl<=l&&r<=dr){
		  sum[now]+=k*(r-l+1);
		  up[now]+=k;
		  return ;
	  }
	  pushdown(now,l,r);
	  ll mid=(l+r)>>1;
	  if(dl<=mid) update(dl,dr,l,mid,lef(now),k); 
	  if(dr>mid) update(dl,dr,mid+1,r,rig(now),k); 
	  pushup(now);
  }
  ll query(ll dl,ll dr,ll l,ll r,ll now){
	  ll res=0;
	  if(dl<=l&&r<=dr) return sum[now];
	  ll mid=(l+r)>>1;
	  pushdown(now,l,r);
	  if(dl<=mid) res+=query(dl,dr,l,mid,lef(now)); 
	  if(dr>mid) res+=query(dl,dr,mid+1,r,rig(now)); 
	  return res;
  }
}
void dfs1(int u,int f){
	fa[u]=f;
	size[u]=1;
	dep[u]=dep[f]+1;
	int h=-1;
	aut(u){
	  int v=to[i];
	  if(v==f) continue;
	  dfs1(v,u);
	  size[u]+=size[v];
	  if(size[v]>h){
	  	h=size[v];
	  	son[u]=v;
	  }
	}
}
void dfs2(int u,int f){
	link[u]=f;
	dfn[u]=++cnt;
    if(!son[u]) return ;
    dfs2(son[u],f);
	aut(u){
	  int v=to[i];
	  if(v==fa[u]||v==son[u]) continue;
      dfs2(v,v);
	}
}
ll queryPath(int u,int v){
	ll res=0;
	while(link[u]!=link[v]){
		if(dep[link[u]]<dep[link[v]])
		  swap(u,v);
	    res=(res+segment::query(dfn[link[u]],dfn[u],1,n,1));
	    u=fa[link[u]];
	}
	if(dep[u]>dep[v])
		swap(u,v);
	res=(res+segment::query(dfn[u],dfn[v],1,n,1));	
	return res;
}
int main(){
    n=rd(); m=rd();
    for(int i=1;i<=n;i++) val[i]=rd();
    for(int i=1;i<=n-1;i++){
    	int x=rd(),y=rd();
    	add(x,y); add(y,x);
    }
    dfs1(1,0);
    dfs2(1,1);
    segment::build(1,1,n);
    while(m--){
    	int typ=rd(),x,y;
    	if(typ==1){
    		x=rd(); y=rd();
    		segment::update(dfn[x],dfn[x],1,n,1,y);
		}
		if(typ==2){
			x=rd(); y=rd();
			segment::update(dfn[x],dfn[x]+size[x]-1,1,n,1,y);
		}
		if(typ==3){
			x=rd();
			printf("%lld\n",queryPath(x,1));
		}
	}
    return 0;
}
2021/5/26 14:00
加载中...