[bzoj4372]烁烁的游戏
动态点分,需要注意的是我们对于每个点要开两个数组,另外一个相当于一个容斥,即把他父亲上的减掉。
- 代码
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5,inf=1e9;
char getopt(){
char x=0;while(x<'A'||x>'Z')x=getchar();
return x;
}
char opt;
struct data{
int lch,rch,x;
}t[N*60];
int n,m,root[N],root1[N],hed[N],nxt[N],to[N],ans,sum,rt,tot,sz;
int f[N],mi[20],anc[N][20],size[N],dep[N],vis[N],belong[N];
void getroot(int x,int pre){
f[x]=0,size[x]=1;
for(int i=hed[x];i;i=nxt[i]){
if(to[i]==pre||vis[to[i]])continue;
getroot(to[i],x);
size[x]+=size[to[i]];
f[x]=max(f[x],size[to[i]]);
}
f[x]=max(f[x],sum-size[x]);
if(f[x]<f[rt])rt=x;
}
void dfs(int x,int fthr){
dep[x]=dep[fthr]+1;
for(int i=1;i<=17;i++){
if(dep[x]-mi[i]<0)break;
anc[x][i]=anc[anc[x][i-1]][i-1];
}
for(int i=hed[x];i;i=nxt[i]){
if(to[i]==fthr)continue;
anc[to[i]][0]=x;
dfs(to[i],x);
}
}
int lca(int x,int y){
if(dep[x]<dep[y])swap(x,y);
int k=dep[x]-dep[y];
for(int i=0;i<=17;i++)
if((k>>i)&1)x=anc[x][i];
if(x==y)return x;
for(int i=17;i>=0;i--){
if(anc[x][i]!=anc[y][i])
x=anc[x][i],y=anc[y][i];
}
return anc[x][0];
}
int dis(int x,int y){return dep[x]+dep[y]-2*dep[lca(x,y)];}
void build(int x){
vis[x]=1;
for(int i=hed[x];i;i=nxt[i]){
if(vis[to[i]])continue;
rt=0;sum=size[to[i]];
getroot(to[i],x);
belong[rt]=x;
build(rt);
}
}
void insert(int &i,int l,int r,int x,int d){
if(!i)i=++sz;
t[i].x+=d;
if(l==r)return;
int mid=(l+r)>>1;
if(x<=mid)insert(t[i].lch,l,mid,x,d);
else insert(t[i].rch,mid+1,r,x,d);
}
int qry(int now,int l,int r,int ll,int rr){
if(ll<=l&&r<=rr)return t[now].x;
int mid=(l+r)>>1;
int ans=0;
if(ll<=mid) ans+=qry(t[now].lch,l,mid,ll,rr);
if(rr>mid) ans+=qry(t[now].rch,mid+1,r,ll,rr);
return ans;
}
void change(int u,int x,int d,int w){
int D=dis(u,x);
if(d-D>=0)insert(root[u],0,n,d-D,w);
int v=belong[u];
if(!v)return;
D=dis(x,v);
if(d-D>=0)insert(root1[u],0,n,d-D,w);
change(v,x,d,w);
}
void calc(int u,int x){
if(u==x)ans+=qry(root[u],0,n,0,n);
else{
int d=dis(u,x);
ans+=qry(root[u],0,n,d,n);
}
if(!belong[u])return;
int d=dis(belong[u],x);
ans-=qry(root1[u],0,n,d,n);
calc(belong[u],x);
}
void add(int x,int y){
tot++;nxt[tot]=hed[x],to[tot]=y;hed[x]=tot;
tot++;nxt[tot]=hed[y],to[tot]=x;hed[y]=tot;
}
int main()
{
mi[0]=1;
for(int i=1;i<=1;i++)mi[i]=mi[i-1]<<1;
scanf("%d%d",&n,&m);
for(int i=1;i<n;i++){
int x,y;scanf("%d%d",&x,&y);
add(x,y);
}
dfs(1,0);
rt=0;f[0]=inf;sum=n;
getroot(1,0);build(rt);
while(m--){
opt=getopt();
int x,d,w;
if(opt=='Q'){
scanf("%d",&x);
ans=0;
calc(x,x);
printf("%d\n",ans);
}else{
scanf("%d%d%d",&x,&d,&w);
d=min(d,n);
change(x,x,d,w);
}
}
}