动态点分治裸题
#include<iostream>
#include<cstring>
#include<cstdio>
#include<map>
#include<algorithm>
#define N 100010
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
struct edges{
int to,pre;
}e[N<<1];int h[N],etop,List[N],Lcnt;
inline int add_edge(int u,int v)
{
return e[++etop].to=v,e[etop].pre=h[u],h[u]=etop;
}
struct segment{
int l,r,pt;
segment *ch[2];
}*rt[N];int sz[N],d[N],pre[N];
map<int,int> zid[N],len[N],dz[N];
map<int,segment*> rtz[N];bool vis[N];
int build(segment* &rt,int l,int r)
{
rt=new segment,rt->l=l,rt->r=r,rt->pt=0;
int mid=(l+r)>>1;if(l==r) return 0;
return build(rt->ch[0],l,mid),build(rt->ch[1],mid+1,r);
}
int update(segment* &rt,int s,int t,int v)
{
int l=rt->l,r=rt->r,mid=(l+r)>>1;
if(s<=l&&r<=t) return rt->pt+=v;
if(s<=mid) update(rt->ch[0],s,t,v);
if(mid<t) update(rt->ch[1],s,t,v);
return 0;
}
int query(segment* &rt,int p)
{
int l=rt->l,r=rt->r,mid=(l+r)>>1;
if(l==r) return rt->pt;int ans=rt->pt;
if(p<=mid) return ans+query(rt->ch[0],p);
else return ans+query(rt->ch[1],p);
}
int getsz(int x,int fa)
{
sz[x]=1;
for(int i=h[x],y;i;i=e[i].pre)
if(!vis[y=e[i].to]&&e[i].to!=fa)
sz[x]+=getsz(y,x);
return sz[List[++Lcnt]=x];
}
int getrt(int &x)
{
for(int i=1,fsz=sz[x],t=fsz;i<=Lcnt;i++)
{
int y=List[i],ysz=fsz-sz[y];
for(int j=h[y];j;j=e[j].pre)
if(sz[e[j].to]<sz[y]) ysz=max(ysz,sz[e[j].to]);
if(ysz<t) t=ysz,x=y;
}
return Lcnt=0;
}
int solve(int x,int fa,int y,int z,int dis)
{
len[x][y]=dis,d[y]=max(d[y],dis),
zid[x][y]=z,dz[y][z]=max(dz[y][z],dis);
for(int i=h[x],t;i;i=e[i].pre)
if(!vis[t=e[i].to]&&e[i].to!=fa)
solve(t,x,y,z,dis+1);
return 0;
}
int dfs(int x,int las)
{
getsz(x,0),getrt(x),pre[x]=las,vis[x]=true;
for(int i=h[x],y;i;i=e[i].pre)
if(!vis[y=e[i].to])
solve(y,x,x,y,1),build(rtz[x][y],0,dz[x][y]);
build(rt[x],0,d[x]);
for(int i=h[x],y;i;i=e[i].pre)
if(!vis[y=e[i].to]) dfs(y,x);
return 0;
}
inline int update(int x,int dis,int w)
{
update(rt[x],0,min(d[x],dis),w);
for(int y=pre[x];y;y=pre[y])
{
int z=zid[x][y],l=len[x][y];
if(l>dis) continue;
update(rt[y],0,min(dis-l,d[y]),w),
update(rtz[y][z],0,min(dis-l,dz[y][z]),w);
}
return 0;
}
inline int query(int x)
{
int ans=query(rt[x],0);
for(int y=pre[x];y;y=pre[y])
{
int z=zid[x][y],l=len[x][y];
ans+=query(rt[y],l)-query(rtz[y][z],l);
}
return ans;
}
char opt[10];
int main()
{
int n,m;scanf("%d%d",&n,&m);
for(int i=1;i<n;i++)
{
int u,v;scanf("%d%d",&u,&v);
add_edge(u,v),add_edge(v,u);
}
dfs(1,0);
while(m--)
{
scanf("%s",opt);int x,l,w;
if(opt[0]=='Q') scanf("%d",&x),printf("%d\n",query(x));
else scanf("%d%d%d",&x,&l,&w),update(x,l,w);
}
return 0;
}