牛客多校第七场C-A National Pandemic(树链剖分)

Description

牛客多校第七场C-A National Pandemic(树链剖分)_第1张图片

Solution

  • 对operation-1
    f ( y ) ← f ( y ) + w − dis ⁡ ( x , y ) f(y) \gets f(y)+w-\operatorname{dis}(x,y) f(y)f(y)+wdis(x,y)
       = w − ( d e p ( x ) + d e p ( y ) − 2 ∗ d e p ( l c a ( x , y ) ) ) \qquad\,\,=w-(dep(x)+dep(y)-2*dep(lca(x,y))) =w(dep(x)+dep(y)2dep(lca(x,y)))
       = w − d e p ( x ) − d e p ( y ) + 2 ∗ d e p ( l c a ( x , y ) ) \qquad\,\,=w-dep(x)-dep(y)+2*dep(lca(x,y)) =wdep(x)dep(y)+2dep(lca(x,y))
    每次操作记 A ← A + w − d e p ( x ) , B ← B + 1 A \gets A+w-dep(x),B \gets B+1 AA+wdep(x),BB+1
    ∴ f ( y ) = A − B ∗ d e p ( y ) + 2 ∗ d e p ( l c a ( x , y ) ) \therefore f(y)=A-B*dep(y)+2*dep(lca(x,y)) f(y)=ABdep(y)+2dep(lca(x,y))
  • 对operation-2
    每次操作记 c i ← c i + min ⁡ ( 0 , f ( y ) ) − f ( y ) c_i \gets c_i+\min(0,f(y))-f(y) cici+min(0,f(y))f(y),最后一起统计
  • 对operation-3
    容易发现 dep ⁡ ( l c a ( x , y ) ) \operatorname{dep}(lca(x,y)) dep(lca(x,y)) y y y到根的路径上与 x x x到根的路径重合的长度,因此每次把 x x x到根 + 1 +1 +1,边转点维护 f ( x ) f(x) f(x)
#include 
#define ls x<<1
#define rs x<<1|1
#define ll long long
const int N=50010;
using namespace std;
int id,d[N],idx[N],son[N],sz[N],fx[N],ldfn[N],top[N],rdfn[N],tot,h[N],mp[N],A,B,c[N];
struct Edge{int v,nxt;}e[N<<1];
struct Seg{int l,r;ll val,inc;}T[N<<2];
void add(int x,int y){e[++tot].v=y,e[tot].nxt=h[x],h[x]=tot;}
void dfs1(int x)
{
	sz[x]=1,son[x]=0;
	for(int i=h[x],v;~i;i=e[i].nxt)if((v=e[i].v)^fx[x])
		d[v]=d[x]+1,fx[v]=x,dfs1(v),sz[x]+=sz[v],son[x]=sz[v]>sz[son[x]]?v:son[x];
}
void dfs2(int x,int tp)
{
	top[x]=tp,ldfn[x]=++id,idx[id]=x;
	if(son[x]) dfs2(son[x],tp);
	for(int i=h[x],v;~i;i=e[i].nxt)if((v=e[i].v)^fx[x]&&v^son[x]) dfs2(v,v);
	rdfn[x]=id;
}
void up(int x){T[x].val=T[ls].val+T[rs].val;}
void down(int x)
{
	if(T[x].inc)
	{
		T[x].val+=T[x].inc*(T[x].r-T[x].l+1);
		T[ls].inc+=T[x].inc;
		T[rs].inc+=T[x].inc;
		T[x].inc=0;
	}
}
void build(int x,int l,int r)
{
	T[x].l=l,T[x].r=r,T[x].inc=0;
	if(l==r){T[x].val=0;return ;}
	int m=l+r>>1;
	build(ls,l,m),build(rs,m+1,r),up(x);
}
void modify(int x,int l,int r,ll val)
{
	if(T[x].l==l&&T[x].r==r){T[x].inc+=val;return ;}
	T[x].val+=(r-l+1)*val;
	int m=T[x].l+T[x].r>>1;
	if(r<=m) modify(ls,l,r,val);
	else if(l>m) modify(rs,l,r,val);
	else modify(ls,l,m,val),modify(rs,m+1,r,val);
}
ll query(int x,int l,int r)
{
	if(T[x].l==l&&T[x].r==r){return T[x].val+T[x].inc*(r-l+1);}
	down(x);int m=T[x].l+T[x].r>>1;
	if(r<=m) return query(ls,l,r);
	else if(l>m) return query(rs,l,r);
	else return query(ls,l,m)+query(rs,m+1,r);
}
void chain_modify(int x,int y,ll val)
{
	while(top[x]^top[y]){
		if(d[top[x]]>d[top[y]]) x^=y^=x^=y;
		modify(1,ldfn[top[y]],ldfn[y],val),y=fx[top[y]];
	}if(d[x]>d[y]) x^=y^=x^=y;
	if(x==y) return ;
	modify(1,ldfn[x],ldfn[y],val);
}
ll chain_query(int x,int y)
{
	ll ret=A-B*d[x]+c[x];
	while(top[x]^top[y]){
		if(d[top[x]]>d[top[y]]) x^=y^=x^=y;
		ret+=query(1,ldfn[top[y]],ldfn[y]),y=fx[top[y]];
	}if(d[x]>d[y]) x^=y^=x^=y;
	if(x==y) return ret;
	return ret+query(1,ldfn[x]+1,ldfn[y]);
}
int main()
{
	int T,cas=0,n,m,p,rt,i,u,v,k,op;
	ll val;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d%d",&n,&m);
		memset(h,-1,sizeof(h)),tot=id=A=B=0;
		memset(c,0,sizeof(c));
		for(i=1;i<n;++i) scanf("%d%d",&u,&v),add(u,v),add(v,u);
		dfs1(1),dfs2(1,1),build(1,1,id);
		while(m--)
		{
			scanf("%d%d",&op,&u);
			if(op==1) scanf("%lld",&val),chain_modify(1,u,2ll),A+=val-d[u],++B;
			if(op==2) val=chain_query(u,1),c[u]+=min(0ll,val)-val;
			if(op==3) printf("%lld\n",chain_query(u,1));
		}
	}
}

你可能感兴趣的:(2020牛客暑期多校训练营)