[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 }

 

posted @ 2019-01-21 09:27  HocRiser  阅读(205)  评论(0编辑  收藏  举报