【问题描述】
魔法森林里有很多蘑菇,魔法使常常采摘它们来制作魔法药水。为了在6月的那个奇妙的晚上用魔法绽放出最绚丽的烟花,魔法使决定对魔法森林进行一番彻底的勘探。
魔法森林分为n个区域,由n-1条长度相等的道路将它们连接为了无向连通图。每个区域都有一个等级,这n个区域的等级满足如下性质:
①1号区域的等级为1;
②由一条道路连接的两个区域(即相邻两个区域)等级相差为1;
③设两个区域x,y被一条道路连接,若x到1号区域的最短距离小于y到1号区域的最短距离,则有x到1号区域的最短路径上的所有区域的等级必定小于y的等级。
由于魔法森林各个区域的气候、地形、水文的不同,每个区域都有一个精华值,其中第i号区域的精华值为wi。整片魔法森林还有一个共鸣度m。每个区域吸收的精华值为一个包含该区域的连通子图的精华值之和,由于共鸣度限制,能被一个区域吸收精华值的所有区域的等级必须比该区域的等级高x,x为不超过m的自然数。举个例子:
魔法使希望得到每个区域所吸收的精华值,这将有助于她规划蘑菇的采摘,于是她把这个任务交给了你,因为她还要去住在这附近的另一位魔法使家中喝杯茶。
【数据范围】
对于20%的数据,n,m<=1000;
对于70%的数据,n,m<=10^5;
对于另外10%的数据,m=n;
对于100%的数据,0<=n,m<=10^6,0<wi<=1000。
————————————————我是分割线————————————————
我们理解完这道题目后,显然就可以明白一个点对于答案的贡献就是在从该点开始向上爬m步所经过的节点上加上该点的精华值
所以就是在一个区间上增加自己的精华值
当然就可以用树上差分啦!
思路清晰,没什么可说的
下面贴代码
#include<cstdio> using namespace std; int val[1000005]; int st[1000005]; int fa[1000005]; int num,n,m,tp; int head[1000005]; struct edge{ int to,next; }g[2000005]; void ins(int u,int v){g[++num].next=head[u];head[u]=num;g[num].to=v;} void insw(int u,int v){ins(u,v);ins(v,u);} void dfs(int u,int fat) { register int y=tp-m; if(y<0)y=0; fa[st[y]]-=val[u];fa[u]+=val[u];st[++tp]=u; for(int i=head[u];i;i=g[i].next) { if(g[i].to==fat)continue; dfs(g[i].to,u); fa[u]+=fa[g[i].to]; } tp--; } int main(){ freopen("mushroom.in","r",stdin); freopen("mushroom.out","w",stdout); scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)scanf("%d",&val[i]); int x,y; for(int i=1;i<n;i++) { scanf("%d%d",&x,&y); insw(x,y); } dfs(1,0); for(int i=1;i<=n;i++)printf("%d\n",fa[i]); fclose(stdin); fclose(stdout); }
时间: 2024-10-06 15:18:42