[BZOJ4372]烁烁的游戏(动态点分治+线段树)
和[BZOJ3730]震波几乎一样,每个点建两棵线段树分别代表它的管辖范围内以它为LCA的路径的贡献和它对父亲的贡献。
注意点分树上的点的距离在原树上不单调,所以不能有若距离超出限制就break之类的判断。
1 #include<cstdio> 2 #include<algorithm> 3 #define lson ls[x],L,mid 4 #define rson rs[x],mid+1,R 5 #define rep(i,l,r) for (int i=(l); i<=(r); i++) 6 #define For(i,x) for (int i=h[x],k; i; i=nxt[i]) 7 using namespace std; 8 9 const int N=200010,M=20000010; 10 char ch; 11 int n,m,u,v,rt,x,d,w,nd,cnt,tim,dep[N],dfn[N],fa[N],lg2[N],sz[N]; 12 int h[N],to[N<<1],nxt[N<<1],sm[M],ls[M],rs[M],mn[N][21],rt1[N],rt2[N],f[N],vis[N]; 13 14 void add(int u,int v){ to[++cnt]=v; nxt[cnt]=h[u]; h[u]=cnt; } 15 16 void dfs(int x,int fa){ 17 dep[x]=dep[fa]+1; mn[++tim][0]=dep[x]; dfn[x]=tim; 18 For(i,x) if ((k=to[i])!=fa) dfs(k,x),mn[++tim][0]=dep[x]; 19 } 20 21 int dis(int x,int y){ 22 int l=dfn[x],r=dfn[y]; 23 if (l>r) swap(l,r); 24 int t=lg2[r-l+1]; 25 return dep[x]+dep[y]-2*min(mn[l][t],mn[r-(1<<t)+1][t]); 26 } 27 28 void find(int x,int F,int S,int &rt){ 29 sz[x]=1; f[x]=0; 30 For(i,x) if ((k=to[i])!=F && !vis[k]) 31 find(k,x,S,rt),sz[x]+=sz[k],f[x]=max(f[x],sz[k]); 32 f[x]=max(f[x],S-sz[x]); 33 if (f[x]<f[rt]) rt=x; 34 } 35 36 void devide(int x){ 37 vis[x]=1; 38 For(i,x) if (!vis[k=to[i]]){ 39 int rt=0; find(k,x,sz[k],rt); fa[rt]=x; devide(rt); 40 } 41 } 42 43 void mdf(int &x,int L,int R,int pos,int k){ 44 if (!x) x=++nd; sm[x]+=k; 45 if (L==R) return; 46 int mid=(L+R)>>1; 47 if (pos<=mid) mdf(lson,pos,k); else mdf(rson,pos,k); 48 } 49 50 int que(int x,int L,int R,int pos){ 51 if (L==R) return sm[x]; 52 int mid=(L+R)>>1; 53 if (pos<=mid) return sm[rs[x]]+que(lson,pos); 54 else return que(rson,pos); 55 } 56 57 void Mdf(int x,int d,int w){ 58 for (int i=x; i; i=fa[i]){ 59 if (d>=dis(i,x)) mdf(rt1[i],0,n,d-dis(i,x),w); 60 if (fa[i] && d>=dis(fa[i],x)) mdf(rt2[i],0,n,d-dis(fa[i],x),w); 61 } 62 } 63 64 int Que(int x){ 65 int res=0; 66 for (int i=x; i; i=fa[i]){ 67 res+=que(rt1[i],0,n,dis(i,x)); 68 if (fa[i]) res-=que(rt2[i],0,n,dis(fa[i],x)); 69 } 70 return res; 71 } 72 73 int main(){ 74 freopen("bzoj4372.in","r",stdin); 75 freopen("bzoj4372.out","w",stdout); 76 scanf("%d%d",&n,&m); 77 rep(i,2,n) scanf("%d%d",&u,&v),add(u,v),add(v,u); 78 dfs(1,0); 79 rep(j,1,20) rep(i,1,tim-(1<<j)+1) 80 mn[i][j]=min(mn[i][j-1],mn[i+(1<<(j-1))][j-1]); 81 lg2[1]=0; rep(i,2,tim) lg2[i]=lg2[i>>1]+1; 82 f[0]=n+1; find(1,0,n,rt); devide(rt); 83 rep(i,1,m){ 84 scanf(" %c",&ch); 85 if (ch=='Q') scanf("%d",&x),printf("%d\n",Que(x)); 86 else scanf("%d%d%d",&x,&d,&w),Mdf(x,d,w); 87 } 88 return 0; 89 }