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

Sample Output

2
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 

 

posted @ 2018-01-27 16:16  Z-Y-Y-S  阅读(362)  评论(0编辑  收藏  举报