BZOJ 4372 烁烁的游戏
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<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 using namespace std; 7 #define MAX 120000 8 struct Node 9 { 10 int next,to; 11 }edge[MAX<<1]; 12 int num,head[MAX]; 13 int dep[MAX],fa[MAX],pos,size[MAX],minsize,root; 14 int FA[MAX],son[MAX],top[MAX],Size; 15 int lazy[MAX*150]; 16 int ch[MAX*150][2],RT[MAX<<1],n,m; 17 int ans,val[MAX]; 18 bool vis[MAX]; 19 inline int gi() 20 { 21 int x=0,flag=1; 22 char ch=getchar(); 23 while (ch<'0'||ch>'9') 24 { 25 if (ch=='-') flag=-1; 26 ch=getchar(); 27 } 28 while (ch>='0'&&ch<='9') 29 { 30 x=(x<<3)+(x<<1)+ch-'0'; 31 ch=getchar(); 32 } 33 return x*flag; 34 } 35 inline void add(int u,int v) 36 { 37 num++; 38 edge[num].next=head[u]; 39 head[u]=num; 40 edge[num].to=v; 41 } 42 void dfs1(int x,int pa) 43 { 44 size[x]=1; 45 dep[x]=dep[pa]+1; 46 for (int i=head[x];i;i=edge[i].next) 47 { 48 int v=edge[i].to; 49 if (v==pa) continue; 50 fa[v]=x; 51 dfs1(v,x); 52 size[x]+=size[v]; 53 if (size[son[x]]<size[v]) 54 son[x]=v; 55 } 56 } 57 void dfs2(int x,int tp) 58 { 59 top[x]=tp; 60 if (son[x]) 61 dfs2(son[x],tp); 62 for (int i=head[x];i;i=edge[i].next) 63 { 64 int v=edge[i].to; 65 if (v==fa[x]||v==son[x]) continue; 66 dfs2(v,v); 67 } 68 } 69 int lca(int x,int y) 70 { 71 while (top[x]!=top[y]) 72 { 73 if (dep[top[x]]<dep[top[y]]) swap(x,y); 74 x=fa[top[x]]; 75 } 76 if (dep[x]<dep[y]) return x; 77 return y; 78 } 79 int dis(int x,int y) 80 { 81 return dep[x]+dep[y]-(dep[lca(x,y)]<<1); 82 } 83 void get_root(int x,int pa) 84 { 85 size[x]=1; 86 int ret=0; 87 for (int i=head[x];i;i=edge[i].next) 88 { 89 int v=edge[i].to; 90 if (v==pa||vis[v]) continue; 91 get_root(v,x); 92 size[x]+=size[v]; 93 if (size[v]>ret) ret=size[v]; 94 } 95 if (Size-size[x]>ret) ret=Size-size[x]; 96 if (ret<minsize) minsize=ret,root=x; 97 } 98 void solve(int x,int pa) 99 { 100 vis[x]=1; 101 FA[x]=pa; 102 for (int i=head[x];i;i=edge[i].next) 103 { 104 int v=edge[i].to; 105 if (vis[v]) continue; 106 minsize=n;Size=size[v]; 107 get_root(v,x); 108 solve(root,x); 109 } 110 } 111 void update(int &rt,int l,int r,int L,int R,int w) 112 { 113 if (!rt) rt=++pos; 114 if (l>=L&&r<=R) 115 {lazy[rt]+=w;return;} 116 int mid=(l+r)>>1; 117 if (L<=mid) update(ch[rt][0],l,mid,L,R,w); 118 if (R>mid) update(ch[rt][1],mid+1,r,L,R,w); 119 } 120 int query(int rt,int l,int r,int x) 121 { 122 if (!rt) return 0; 123 if (l==r) 124 return lazy[rt]; 125 int mid=(l+r)>>1; 126 if (x<=mid) return query(ch[rt][0],l,mid,x)+lazy[rt]; 127 else return query(ch[rt][1],mid+1,r,x)+lazy[rt]; 128 } 129 void change(int u,int k,int w) 130 { 131 update(RT[u],0,n,0,k,w); 132 for (int i=u;FA[i];i=FA[i]) 133 { 134 int d=dis(u,FA[i]); 135 if (d>k) continue; 136 update(RT[FA[i]],0,n,0,k-d,w); 137 update(RT[i+n],0,n,0,k-d,w); 138 } 139 } 140 void ask(int u) 141 { 142 ans+=query(RT[u],0,n,0); 143 for (int i=u;FA[i];i=FA[i]) 144 { 145 int d=dis(u,FA[i]); 146 ans+=query(RT[FA[i]],0,n,d); 147 ans-=query(RT[i+n],0,n,d); 148 } 149 } 150 int main() 151 {int u,v; 152 char s[10]; 153 cin>>n>>m; 154 for (int i=1;i<=n-1;i++) 155 { 156 u=gi();v=gi(); 157 add(u,v);add(v,u); 158 } 159 dfs1(1,0); 160 dfs2(1,1); 161 minsize=Size=n; 162 get_root(1,0); 163 solve(root,0); 164 ans=0; 165 for (int i=1;i<=m;i++) 166 { 167 scanf("%s",s); 168 if (s[0]=='Q') 169 { 170 ans=0; 171 int x=gi(); 172 ask(x); 173 printf("%d\n",ans); 174 } 175 else 176 { 177 int u=gi(),k=gi(),w=gi(); 178 change(u,k,w); 179 } 180 } 181 return 0; 182 } 183