题意

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

题解

树上路径统计,解法是点分治。点分的时候求出根到每个点路径最大值和权值和。排一序,然后开个桶,就能计算了。去重就套路的减去没棵子树里面的答案。

CODE

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 100005;
typedef long long LL;
LL ans;
int n, mod, fir[MAXN], nxt[MAXN<<1], to[MAXN<<1], cnt, val[MAXN];
inline void link(int x, int y) {
to[++cnt] = y; nxt[cnt] = fir[x]; fir[x] = cnt;
to[++cnt] = x; nxt[cnt] = fir[y]; fir[y] = cnt;
}
bool ban[MAXN];
int getsz(int u, int ff) {
int re = 1;
for(int v, i = fir[u]; i; i = nxt[i])
if((v=to[i]) != ff && !ban[v])
re += getsz(v, u);
return re;
}
int getrt(int u, int ff, int &rt, int Size) {
int re = 1; bool can = 1;
for(int v, tmp, i = fir[u]; i; i = nxt[i])
if((v=to[i]) != ff && !ban[v]) {
re += (tmp = getrt(v, u, rt, Size));
if((tmp<<1) > Size) can = 0;
}
if(((Size-re)<<1) > Size) can = 0;
if(can) rt = u;
return re;
}
struct node {
int mx, v;
inline bool operator <(const node &o)const {
return mx < o.mx;
}
}seq[MAXN], vv[MAXN];
int tot;
void dfs(int u, int ff, int mx, int vs) {
vs = (vs + val[u]) % mod;
mx = max(mx, val[u]);
vv[u] = (node){ mx, vs };
for(int v, i = fir[u]; i; i = nxt[i])
if((v=to[i]) != ff && !ban[v])
dfs(v, u, mx, vs);
}
void push(int u, int ff) {
seq[++tot] = vv[u];
for(int v, i = fir[u]; i; i = nxt[i])
if((v=to[i]) != ff && !ban[v])
push(v, u);
}
int bin[10000005];
LL calc(int rt, int o) {
tot = 0; push(rt, 0);
sort(seq + 1, seq + tot + 1);
LL re = 0;
for(int i = 1; i <= tot; ++i) {
re += bin[((seq[i].mx+o-seq[i].v)%mod+mod)%mod];
++bin[seq[i].v%mod];
}
for(int i = 1; i <= tot; ++i) --bin[seq[i].v%mod];
return re;
}
void solve(int x) {
dfs(x, 0, 0, 0);
ans += calc(x, val[x]);
ban[x] = 1;
for(int v, i = fir[x]; i; i = nxt[i])
if(!ban[v=to[i]]) ans -= calc(v, val[x]);
}
void TDC(int x) {
int Size = getsz(x, 0);
getrt(x, 0, x, Size);
solve(x);
for(int v, i = fir[x]; i; i = nxt[i])
if(!ban[v=to[i]]) TDC(v);
}
int main () {
scanf("%d%d", &n, &mod);
for(int i = 1, x, y; i < n; ++i)
scanf("%d%d", &x, &y), link(x, y);
for(int i = 1; i <= n; ++i) scanf("%d", &val[i]);
TDC(1);
printf("%lld\n", ans+n);
}

某模拟赛C题 树上路径统计 (点分治)的更多相关文章

  1. 【2019.8.6 慈溪模拟赛 T2】树上路径(tree)(Trie)

    从暴力考虑转化题意 考虑最暴力的做法,我们枚举路径的两端,然后采用类似求树上路径长度的做法,计算两点到根的贡献,然后除去\(LCA\)到根的贡献两次. 即,设\(v_i\)为\(i\)到根路径上的边权 ...

  2. 【JZOJ4715】【NOIP2016提高A组模拟8.19】树上路径

    题目描述 给出一棵树,求出最小的k,使得,且在树中存在路径p,使得k>=S且k<=E.(k为路径p上的边的权值和) 输入 第一行给出N,S,E.N代表树的点数,S,E如题目描述. 下面N- ...

  3. 6.28 NOI模拟赛 好题 状压dp 随机化

    算是一道比较新颖的题目 尽管好像是两年前的省选模拟赛题目.. 对于20%的分数 可以进行爆搜,对于另外20%的数据 因为k很小所以考虑上状压dp. 观察最后答案是一个连通块 从而可以发现这个连通块必然 ...

  4. 【csp模拟赛6】树上统计-启发式合并,线段树合并

    30%:暴力 40%:枚举L,R从L~n枚举,R每增大一个,更新需要的边(bfs实现)60%:枚举每条边, 计算每条边的贡献另外20%的数据:枚举每条边,计算每条边的贡献100%:对于每一条边统计 有 ...

  5. newcoder NOIP提高组模拟赛C题——保护

    我是发了疯才来写这道题的 我如果用写这道题的时间去写dp,我估计我能写上三四道 可怕的数据结构题 题目 这道题的鬼畜之处在于实在是不太好写 我们看到要求离树根尽量的近,所以我们很容易就能想到树上倍增, ...

  6. 2016 10 26考试 NOIP模拟赛 杂题

    Time 7:50 AM -> 11:15 AM 感觉今天考完后,我的内心是崩溃的 试题 考试包 T1: 首先看起来是个贪心,然而,然而,看到那个100%数据为n <= 2000整个人就虚 ...

  7. 【2019.10.7 CCF-CSP-2019模拟赛 T1】树上查询(tree)(思维)

    思维 这道题应该算是一道思维题吧. 首先你要想到,既然这是一棵无根树,就要明智地选择根--以第一个黑点为根(不要像我一样习惯性以\(1\)号点为根,结果直到心态爆炸都没做出来). 想到这一点,这题就很 ...

  8. 6.29 省选模拟赛 坏题 AC自动机 dp 图论

    考场上随手构造了一组数据把自己卡掉了 然后一直都是掉线状态了. 最后发现这个东西不是subtask -1的情况不多 所以就没管无解直接莽 写题有点晚 故没调出来.. 考虑怎么做 容易想到建立AC自动机 ...

  9. 9 16 模拟赛&关于线段树上二分总结

    1 考试时又犯了一个致命的错误,没有去思考T2的正解而是去简单的推了一下式子开始了漫漫找规律之路,不应该这样做的 为了得到规律虽然也打了暴力 但是还是打了一些不必要的程序 例如求组合数什么的比较浪费时 ...

随机推荐

  1. c++性能测试工具:计算时间复杂度

    有时候除了测量算法的具体性能指数,我们也会希望测试出算法的时间复杂度,以便我们对待测试的算法的性能有一个更加直观的了解. 测量时间复杂度 google benchmark已经为我们提供了类似的功能,而 ...

  2. vscode java

    https://devblogs.microsoft.com/visualstudio/announcing-visual-studio-code-java-installer/ public cla ...

  3. proxy 简化版本

    public interface People { public String eat(String param); } public class Jack implements People { @ ...

  4. 我的周记10——“知行合一"

    印象中有个名人说过一句名言:与其游手好闲地学习,不如学习游手好闲 来自 玉伯 .  字是真的好看,有风格 现在已经是第十篇周记了,写着写着慢慢偏离了初衷,但庆幸的是坚持下来写.我相信在用心写好每篇周记 ...

  5. hbase 待看代码

    flush split mvcc rpc get put mutation netty  reactor模型 page cache 缓存 I/O 又被称作标准 I/O,大多数文件系统的默认 I/O 操 ...

  6. 图解微信小程序---获取电影列表

    图解微信小程序---获取电影列表 代码笔记 list跳转 第一步:编写前端页面获取相关的电影列表参数(对于显示参数不熟悉,可以先写js,通过console  Log的方式获取我们电影的相关数据字段,后 ...

  7. 前端学习:学习笔记(CSS部分)

    前端学习:学习笔记(CSS部分) CSS的学习总结(图解) CSS的引入方式和书写规范 CSS的插入方式_内嵌样式 <!DOCTYPE html> <html> <hea ...

  8. 【03】Kubernets:K8S 操作入门

    写在前面的话 经过上一节,我们顺利将 K8S 集群搭建了起来,在其中我也简单的谈了一下关于 K8S 的网络.那么这一节我们主要谈谈如何来简单的使用 K8S 的命令.当然这些命令有很多,我们只是通过一个 ...

  9. 单片机成长之路(stm8基础篇)- 025 stm8 时钟切换

    stm8 时钟切换; /************************************ 时钟设置 ************************************/ // 时钟 0: ...

  10. web api与mvc的区别

    MVC主要用来构建网站,既关心数据也关心页面展示,而Web API只关注数据 Web API支持格式协商,客户端可以通过Accept header通知服务器期望的格式 Web API支持Self Ho ...