BZOJ4372: 烁烁的游戏(动态点分治)
Description
背景:烁烁很喜欢爬树,这吓坏了树上的皮皮鼠。
题意:
给定一颗n个节点的树,边权均为1,初始树上没有皮皮鼠。
烁烁他每次会跳到一个节点u,把周围与他距离不超过d的节点各吸引出w只皮皮鼠。皮皮鼠会被烁烁吸引,所以会一直待在节点上不动。
烁烁很好奇,在当前时刻,节点u有多少个他的好朋友---皮皮鼠。
大意:
给一颗n个节点的树,边权均为1,初始点权均为0,m次操作:
Q x:询问x的点权。
M x d w:将树上与节点x距离不超过d的节点的点权均加上w。
Input
第一行两个正整数:n,m
接下来的n-1行,每行三个正整数u,v,代表u,v之间有一条边。
接下来的m行,每行给出上述两种操作中的一种。
Output
对于每个Q操作,输出当前x节点的皮皮鼠数量。
Sample Input
7 6
1 2
1 4
1 5
2 3
2 7
5 6
M 1 1 2
Q 5
M 2 2 3
Q 3
M 1 2 1
Q 2
1 2
1 4
1 5
2 3
2 7
5 6
M 1 1 2
Q 5
M 2 2 3
Q 3
M 1 2 1
Q 2
Sample Output
2
3
6
3
6
解题思路:
和震波很像,查询修改反过来就好了。
代码:
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 const int N=100010; 5 struct pnt{ 6 int hd; 7 int fa; 8 int f; 9 int tp; 10 int wgt; 11 int mxs; 12 int dis; 13 bool vis; 14 int roota; 15 int rootp; 16 }p[N]; 17 struct trnt{ 18 int ls; 19 int rs; 20 int val; 21 }tr[40000000]; 22 struct ent{ 23 int twd; 24 int lst; 25 }e[N<<1]; 26 int n,m; 27 int cnt; 28 int siz; 29 int root; 30 int size; 31 int maxsize; 32 char cmd[1000]; 33 void ade(int f,int t) 34 { 35 cnt++; 36 e[cnt].twd=t; 37 e[cnt].lst=p[f].hd; 38 p[f].hd=cnt; 39 return ; 40 } 41 void Basic_dfs(int x,int f) 42 { 43 p[x].dis=p[f].dis+1; 44 p[x].f=f; 45 p[x].wgt=1; 46 int maxs=-1; 47 for(int i=p[x].hd;i;i=e[i].lst) 48 { 49 int to=e[i].twd; 50 if(to==f) 51 continue; 52 Basic_dfs(to,x); 53 p[x].wgt+=p[to].wgt; 54 if(maxs<p[to].wgt) 55 { 56 maxs=p[to].wgt; 57 p[x].mxs=to; 58 } 59 } 60 return ; 61 } 62 void Build_dfs(int x,int top) 63 { 64 if(!x) 65 return ; 66 p[x].tp=top; 67 Build_dfs(p[x].mxs,top); 68 for(int i=p[x].hd;i;i=e[i].lst) 69 { 70 int to=e[i].twd; 71 if(to==p[x].mxs||to==p[x].f) 72 continue; 73 Build_dfs(to,to); 74 } 75 return ; 76 } 77 int Lca(int x,int y) 78 { 79 while(p[x].tp!=p[y].tp) 80 { 81 if(p[p[x].tp].dis<p[p[y].tp].dis) 82 std::swap(x,y); 83 x=p[p[x].tp].f; 84 } 85 if(p[x].dis>p[y].dis) 86 std::swap(x,y); 87 return x; 88 } 89 int Dis(int x,int y) 90 { 91 int z=Lca(x,y); 92 return p[x].dis+p[y].dis-2*p[z].dis; 93 } 94 void grc_dfs(int x,int f) 95 { 96 p[x].wgt=1; 97 int maxs=-1; 98 for(int i=p[x].hd;i;i=e[i].lst) 99 { 100 int to=e[i].twd; 101 if(to==f||p[to].vis) 102 continue; 103 grc_dfs(to,x); 104 p[x].wgt+=p[to].wgt; 105 if(maxs<p[to].wgt) 106 maxs=p[to].wgt; 107 } 108 maxs=std::max(maxs,size-p[x].wgt); 109 if(maxs<maxsize) 110 { 111 root=x; 112 maxsize=maxs; 113 } 114 return ; 115 } 116 void bin_dfs(int x,int f) 117 { 118 p[x].fa=f; 119 p[x].vis=true; 120 int tmp=size; 121 for(int i=p[x].hd;i;i=e[i].lst) 122 { 123 int to=e[i].twd; 124 if(p[to].vis) 125 continue; 126 root=0; 127 if(p[x].wgt>p[to].wgt) 128 size=p[to].wgt; 129 else 130 size=tmp-p[x].wgt; 131 maxsize=0x3f3f3f3f; 132 grc_dfs(to,to); 133 bin_dfs(root,x); 134 } 135 return ; 136 } 137 void update(int &spc,int l,int r,int ll,int rr,int v) 138 { 139 if(ll>r||l>rr) 140 return ; 141 if(!spc) 142 spc=++siz; 143 if(ll<=l&&r<=rr) 144 { 145 tr[spc].val+=v; 146 return ; 147 } 148 int mid=(l+r)>>1; 149 update(tr[spc].ls,l,mid,ll,rr,v); 150 update(tr[spc].rs,mid+1,r,ll,rr,v); 151 return ; 152 } 153 int query(int spc,int l,int r,int pos) 154 { 155 if(!spc) 156 return 0; 157 int ans=tr[spc].val; 158 if(l==r) 159 return ans; 160 int mid=(l+r)>>1; 161 if(pos<=mid) 162 ans+=query(tr[spc].ls,l,mid,pos); 163 else 164 ans+=query(tr[spc].rs,mid+1,r,pos); 165 return ans; 166 } 167 void Update(int x,int k,int val) 168 { 169 update(p[x].rootp,0,n-1,0,k,val); 170 for(int i=x;p[i].fa;i=p[i].fa) 171 { 172 int d=Dis(x,p[i].fa); 173 if(k<d) 174 continue; 175 update(p[p[i].fa].rootp,0,n-1,0,k-d,val); 176 update(p[i].roota,0,n-1,0,k-d,val); 177 } 178 return ; 179 } 180 int Query(int x) 181 { 182 int ans=query(p[x].rootp,0,n-1,0); 183 for(int i=x;p[i].fa;i=p[i].fa) 184 { 185 int d=Dis(x,p[i].fa); 186 ans+=query(p[p[i].fa].rootp,0,n-1,d)-query(p[i].roota,0,n-1,d); 187 } 188 return ans; 189 } 190 int main() 191 { 192 scanf("%d%d",&n,&m); 193 for(int i=1;i<n;i++) 194 { 195 int a,b; 196 scanf("%d%d",&a,&b); 197 ade(a,b); 198 ade(b,a); 199 } 200 Basic_dfs(1,1); 201 Build_dfs(1,1); 202 root=0; 203 size=n; 204 maxsize=0x3f3f3f3f; 205 grc_dfs(1,1); 206 bin_dfs(root,0); 207 while(m--) 208 { 209 scanf("%s",cmd+1); 210 if(cmd[1]=='M') 211 { 212 int x,k,v; 213 scanf("%d%d%d",&x,&k,&v); 214 Update(x,k,v); 215 }else{ 216 int x; 217 scanf("%d",&x); 218 printf("%d\n",Query(x)); 219 } 220 } 221 return 0; 222 }