Description

给定一颗n个结点的无根树,树上的每个点有一个非负整数点权,定义一条路径的价值为路径上的点权和-路径的点权最大值。
给定参数p,我们想知道,有多少不同的树上简单路径,满足它的价值恰好是p的倍数。
注意:单点算作一个路径;u ≠ v时,(u,v)和(v,u)只算一次。

Input

第一行包含两个整数n,p;
接下来n-1行,每行两个整数u,v,表示一条树边。
接下来一行n个整数,第i个整数val_i,表示点i的权值。

Output

 输出包含一行一个整数,表示答案

Sample Input

5 2

1 2

1 3

2 4

3 5

1 3 3 1 2

Sample Output

9

满足条件的路径有:(1,1),(2,2),(3,3),(4,4),(5,5),(1,4),(2,3),(2,5),(3,5)。

Hint

【数据范围与约定】
对所有测试点,我们有: n≤10^5,p≤10^7,val_i≤10^9

这是点分治求倍数的板子,对我来说真是一道好题= =

错点1:注意模运算的余数的意义

错点2:我的x和root不要搞混,调了好久才发现这个问题。。。

错点3:此题合并路径的时候,root的值会被算两次,要减去一个

错点4:写法不同注意的细节有很多。。。像是第一份,对于样例中1->4这种单条合法路径,在处理x=1的时候加了上去,然后容斥的时候又在子树x=2的时候被减了,但是由于带本身,所以实际上是+2-1=1,为什么我觉得这么玄学呢?还是分开处理好(虽然细节非常多,而且常数要大一些)

提供两种写法。

#include<bits/stdc++.h>
using namespace std;
const int Maxn=100005,Maxv=10000005;
struct Edge{int cnt,h[Maxn],to[Maxn*2],next[Maxn*2];inline void add(int x,int y){next[++cnt]=h[x];to[cnt]=y;h[x]=cnt;}
}e;
#define to e.to[p]
int tmpsiz[Maxn];
int n,m,v[Maxn];
bool vst[Maxn];
long long ans;
struct Node{long long mx,dist;bool operator <(const Node&A) const {return mx<A.mx;}
}s[Maxn];int top,sum[Maxv];
void Statistics(int x,int fa,int mx,long long dist){s[++top]=(Node){mx,dist};for(int p=e.h[x];p;p=e.next[p])if(!vst[to]&&to!=fa)Statistics(to,x,max(mx,v[to]),(dist+v[to]));
}
long long Calc(int x,int Re,int prtv){//定点合并的时候重算了一次 top=0;Statistics(x,0,max(prtv,v[x]),(prtv+v[x]));long long ret=0;sort(s+1,s+top+1);for(int i=1;i<=top;++i){ret+=sum[(s[i].dist-s[i].mx)%m];++sum[(m-(s[i].dist-Re)%m+m)%m];}for(int i=1;i<=top;++i)if(((s[i].dist-s[i].mx)%m+m)%m==0)++ret;for(int i=1;i<=top;i++)--sum[(m-(s[i].dist-Re)%m+m)%m];return ret;
}
void Getroot(int x,int fa,int &mn,int &root,int totsiz){tmpsiz[x]=1;int maxsiz=0;for(int p=e.h[x];p;p=e.next[p])if(!vst[to]&&to!=fa){Getroot(to,x,mn,root,totsiz);tmpsiz[x]+=tmpsiz[to];maxsiz=max(maxsiz,tmpsiz[to]);}maxsiz=max(maxsiz,totsiz-tmpsiz[x]);if(maxsiz<mn)mn=maxsiz,root=x;
}
void Divide(int x,int totsiz){int mn=1<<30,root=x;Getroot(x,0,mn,root,totsiz);ans+=Calc(root,v[root],0);vst[root]=1;
//  cout<<root<<' '<<ans<<'\n';for(int p=e.h[root];p;p=e.next[p])if(!vst[to]){ans-=Calc(to,v[root],v[root]);Divide(to,tmpsiz[to]);}
}
int main(){scanf("%d%d",&n,&m);for(int i=1;i<n;++i){int x,y;scanf("%d%d",&x,&y);e.add(x,y),e.add(y,x);}for(int i=1;i<=n;++i)scanf("%d",&v[i]);Divide(1,n);cout<<ans<<'\n';return 0;
}
#include<bits/stdc++.h>
using namespace std;
const int Maxn=100005,Maxv=10000005;
struct Edge{int cnt,h[Maxn],to[Maxn*2],next[Maxn*2];inline void add(int x,int y){next[++cnt]=h[x];to[cnt]=y;h[x]=cnt;}
}e;
#define to e.to[p]
int tmpsiz[Maxn];
int n,m,v[Maxn];
bool vst[Maxn];
long long ans;
struct Node{long long mx,dist;bool operator <(const Node&A) const {return mx<A.mx;}
}s[Maxn];int top,sum[Maxv];
void Statistics(int x,int fa,int mx,long long dist){s[++top]=(Node){mx,dist};for(int p=e.h[x];p;p=e.next[p])if(!vst[to]&&to!=fa)Statistics(to,x,max(mx,v[to]),(dist+v[to]));
}
long long Calc(int x,int Re,int prtv,bool son){//定点合并的时候重算了一次 top=0;if(son)s[++top]=(Node){max(prtv,v[x]),1ll*prtv+v[x]};//容斥时记得加上自己这一条 for(int p=e.h[x];p;p=e.next[p])if(!vst[to])Statistics(to,x,max(prtv,max(v[x],v[to])),(1ll*prtv+v[x]+v[to]));long long ret=0;sort(s+1,s+top+1);for(int i=1;i<=top;++i){ret+=sum[(s[i].dist-s[i].mx)%m];++sum[(m-(s[i].dist-Re)%m+m)%m];}if(!son)for(int i=1;i<=top;++i)//容斥的时候不减单独路径 if(((s[i].dist-s[i].mx)%m+m)%m==0)++ret;for(int i=1;i<=top;i++)--sum[(m-(s[i].dist-Re)%m+m)%m];return ret;
}
void Getroot(int x,int fa,int &mn,int &root,int totsiz){tmpsiz[x]=1;int maxsiz=0;for(int p=e.h[x];p;p=e.next[p])if(!vst[to]&&to!=fa){Getroot(to,x,mn,root,totsiz);tmpsiz[x]+=tmpsiz[to];maxsiz=max(maxsiz,tmpsiz[to]);}maxsiz=max(maxsiz,totsiz-tmpsiz[x]);if(maxsiz<mn)mn=maxsiz,root=x;
}
void Divide(int x,int totsiz){int mn=1<<30,root=x;Getroot(x,0,mn,root,totsiz);ans+=Calc(root,v[root],0,0);vst[root]=1;for(int p=e.h[root];p;p=e.next[p])if(!vst[to]){ans-=Calc(to,v[root],v[root],1);Divide(to,tmpsiz[to]);}
}
int main(){scanf("%d%d",&n,&m);for(int i=1;i<n;++i){int x,y;scanf("%d%d",&x,&y);e.add(x,y),e.add(y,x);}for(int i=1;i<=n;++i)scanf("%d",&v[i]);Divide(1,n);cout<<ans+n<<'\n';return 0;
}

JZOJ5055 树上路径相关推荐

  1. 树上路径(path)

    树上路径(path) 题目描述 在Berland,有n个城堡. 每个城堡恰好属于一个领主.不同的城堡属于不同的领主.在所有领主中有一个是国王,其他的每个领主都直接隶属于另一位领主,并且间接隶属于国王. ...

  2. 【jzoj5055】【GDOI2017模拟二试4.12】【树上路径】【点分治】

    题目大意 给定一颗n个结点的无根树,树上的每个点有一个非负整数点权,定义一条路径的价值为路径上的点权和-路径的点权最大值. 给定参数p,我们想知道,有多少不同的树上简单路径,满足它的价值恰好是p的倍数 ...

  3. CF E2 - Daleks' Invasion (medium) (LCA求两点树上路径上的最大边权)

    http://codeforces.com/contest/1184/problem/E2 题意:给出一副图,首先求出这幅图的最小生成树 , 然后修改这幅图上不属于最小生成树的边权,使得修改后的图在求 ...

  4. SPOJ-COT-Count on a tree(树上路径第K小,可持久化线段树)

    题意: 求树上A,B两点路径上第K小的数 分析: 同样是可持久化线段树,只是这一次我们用它来维护树上的信息. 我们之前已经知道,可持久化线段树实际上是维护的一个前缀和,而前缀和不一定要出现在一个线性表 ...

  5. 点分治——树上路径统计

    点分治: 一种分治的方法,一般用于(在不修改情况下),处理两点树上的两点之间的路径的问题. 每次从当前的子图中找到重心,即点分治"点"的含义. 以重心为当前的根节点,查找一切经过重 ...

  6. jzoj4279-[NOIP2015模拟10.29B组]树上路径【树形dp】

    正题 题目链接:https://gmoj.net/senior/#main/show/4279 题目大意 nnn个点的一棵树求经过每个点的最长路径. 解题思路 设fif_{i}fi​表示iii子树内的 ...

  7. Codeforces 739B Alyona and a tree (树上路径倍增及差分)

    题目链接 Alyona and a tree 弄了好几个小时终于Accepted了,之后发现这个题是Div1的. 比较考验我思维的一道好题. 首先,做一遍DFS预处理出t[i][j]和d[i][j]. ...

  8. 点分治 【BZOJ3784】树上路径

    给定一个N个结点的树,结点用正整数1..N编号.每条边有一个正整数权值.用d(a,b)表示从结点a到结点b路边上经过边的权值.其中要求a < b.将这n*(n-1)/2个距离从大到小排序,输出前 ...

  9. noip2016机房模拟---树上路径

    这道题听说是一道点分的题,但是我不太想写,而且确实不太会 所以呢就随手写了个类似树规的东西 先考虑一个节点的左右节点相互之间的贡献 为了防止转移次数过多 我们把递归的下一层的重儿子的set拿来直接用 ...

最新文章

  1. python 十进制转二进制,十进制转八进制,十进制转十六进制 的方法
  2. Firefox 50优化Electrolysis
  3. ICMP协议抓包分析-wireshark
  4. golang网络编程
  5. 音视频技术开发周刊 72期
  6. 程序员面试金典 - 面试题 01.02. 判定是否互为字符重排(哈希map)
  7. [C++]variadic function template expansion 变元函数参数的展开规则
  8. Linux安装redis(6.0.9)环境
  9. php cms 那个安全,PHPCMS系统安全设置步骤
  10. 关于采用消息钩子机制的透明加密的简单破解
  11. python3 证件照批量换背景
  12. 「CSS畅想」好友想回忆童年,安排~为她做了一个果宝特攻的换装
  13. 空气炸锅如何挑选研究
  14. Django应用及分布式路由
  15. cadence修改板框倒角_Allegro软件中如何对板框进行倒角及倒角不成功解决方法
  16. 我,32岁,小米公司程序员,揭 开北京“码农”的真实收入
  17. WMS、WFS、WMTS、TMS
  18. ThinkPHP高仿蓝奏云网盘系统程序
  19. [NC1105B]下雨天
  20. 使用 OpenCV 识别图片中的猫咪

热门文章

  1. 网易云类音乐--主页与登录界面结构html+css实现(三)
  2. SSM+mysql+微信小程序网易云音乐设计与实现 毕业设计-附源码261620
  3. 世界上这五类人永远不可能成为编程界牛人
  4. 上市公司关于年报、半年报、季报及其公布时间的一些知识
  5. mysql的锁机制,你真的了解吗?进来吧!用图表告诉你
  6. 【教学类-34-01】拼图(运动项目-长方块拼图)3*4格子(中班主题《个别化拼图》健康偏艺术-美术)
  7. 局域网内设置共享打印机并连接使用
  8. 原来路由器的USB接口这么强大!这样设置,路由器秒变私有云盘
  9. 苹果A系列芯片的三年AI进化:为何要大规模升级AI算力?
  10. YYText-显示富文本