Codeforces 494D Birthday 树形dp (看题解)
Birthday
没想到平方和能在树上dp出来的。。。
知道了如何转移, 那么就很好写了。。。
#include<bits/stdc++.h> #define LL long long #define LD long double #define ull unsigned long long #define fi first #define se second #define mk make_pair #define PLL pair<LL, LL> #define PLI pair<LL, int> #define PII pair<int, int> #define SZ(x) ((int)x.size()) #define ALL(x) (x).begin(), (x).end() #define fio ios::sync_with_stdio(false); cin.tie(0);using namespace std;const int N = 1e5 + 7; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const int mod = 1e9 + 7; const double eps = 1e-8; const double PI = acos(-1);template<class T, class S> inline void add(T& a, S b) {a += b; if(a >= mod) a -= mod;} template<class T, class S> inline void sub(T& a, S b) {a -= b; if(a < 0) a += mod;} template<class T, class S> inline bool chkmax(T& a, S b) {return a < b ? a = b, true : false;} template<class T, class S> inline bool chkmin(T& a, S b) {return a > b ? a = b, true : false;}int n, q; int pa[N][20], len[N][20], depth[N]; int allDis2[N];vector<PII> G[N];struct dpNode {dpNode() {cnt = sumDis = sumDis2 = 0;}dpNode(int cnt, int sumDis, int sumDis2) : cnt(cnt), sumDis(sumDis), sumDis2(sumDis2) {}int cnt, sumDis, sumDis2;void print() {printf("cnt: %d sumDis: %d sumDis2: %d\n", cnt, sumDis, sumDis2);} } dp[N], dp2[N], INIT(1, 0, 0);dpNode mergeTwo(dpNode a, dpNode b, int w, int op) {if(op > 0) {a.cnt += b.cnt;add(a.sumDis, b.sumDis);add(a.sumDis, 1LL * b.cnt * w % mod);add(a.sumDis2, b.sumDis2);add(a.sumDis2, 1LL * b.sumDis * 2 * w % mod);add(a.sumDis2, 1LL * w * w % mod * b.cnt % mod);} else {a.cnt -= b.cnt;sub(a.sumDis, b.sumDis);sub(a.sumDis, 1LL * b.cnt * w % mod);sub(a.sumDis2, b.sumDis2);sub(a.sumDis2, 1LL * b.sumDis * 2 * w % mod);sub(a.sumDis2, 1LL * w * w % mod * b.cnt % mod);}return a; }void dfs(int u, int fa, int disTofa) {depth[u] = depth[fa] + 1;pa[u][0] = fa;len[u][0] = disTofa;dp[u].cnt = 1;for(int i = 1; i < 20; i++) {pa[u][i] = pa[pa[u][i - 1]][i - 1];len[u][i] = (len[u][i - 1] + len[pa[u][i - 1]][i - 1]) % mod;}for(auto &e : G[u]) {int v = e.se;if(v == fa) continue;dfs(v, u, e.fi);dp[u] = mergeTwo(dp[u], dp[v], e.fi, 1);} }PII getLca(int u, int v) {if(depth[u] < depth[v]) swap(u, v);int dis = depth[u] - depth[v];int ret = 0;for(int i = 19; i >= 0; i--)if(dis >> i & 1) add(ret, len[u][i]), u = pa[u][i];if(u == v) return mk(ret, u);for(int i = 19; i >= 0; i--) {if(pa[u][i] != pa[v][i]) {add(ret, len[u][i]);add(ret, len[v][i]);u = pa[u][i];v = pa[v][i];}}add(ret, len[u][0]);add(ret, len[v][0]);return mk(ret, pa[u][0]); }void dfs2(int u, int fa, dpNode up) {dp2[u] = up; dp2[u].cnt--;allDis2[u] = (dp[u].sumDis2 + up.sumDis2) % mod;for(auto &e : G[u]) {if(e.se == fa) continue;up = mergeTwo(up, dp[e.se], e.fi, 1);}for(auto &e : G[u]) {if(e.se == fa) continue;up = mergeTwo(up, dp[e.se], e.fi, -1);dfs2(e.se, u, mergeTwo(INIT, up, e.fi, 1));up = mergeTwo(up, dp[e.se], e.fi, 1);} }int main() {scanf("%d", &n);for(int i = 1; i < n; i++) {int u, v, w;scanf("%d%d%d", &u, &v, &w);G[u].push_back(mk(w, v));G[v].push_back(mk(w, u));}dfs(1, 0, 0);dfs2(1, 0, INIT);scanf("%d", &q);while(q--) {int u, v;scanf("%d%d", &u, &v);PII ret = getLca(u, v);int lca = ret.se, dis = ret.fi;int ans = 0;if(lca != v) {int x = mergeTwo(INIT, dp[v], dis, 1).sumDis2;int z = allDis2[u];ans = ((2 * x - z) % mod + mod) % mod;} else {int y = mergeTwo(INIT, dp2[v], dis, 1).sumDis2;int z = allDis2[u];ans = ((z - 2 * y) % mod + mod) % mod;}printf("%d\n", ans);}return 0; }/* */
转载于:https://www.cnblogs.com/CJLHY/p/10988592.html
Codeforces 494D Birthday 树形dp (看题解)相关推荐
- 背包类树形DP 选课题解
题目传送门; 我觉得题目给出0节点作为虚拟课程,也避免了我们要去想将若干个森林建成一棵树:将N个节点的森林建成了N+1条边的树: 其次,我们对这个题进行一个分析: 很容易想到F[x,t]表示以x为根的 ...
- Codeforces 596D Wilbur and Trees dp (看题解)
一直在考虑, 每一段的贡献, 没想到这个东西能直接dp..因为所有的h都是一样的. #include<bits/stdc++.h> #define LL long long #define ...
- Codeforces 709E. Centroids 树形DP
题目链接:http://codeforces.com/contest/709/problem/E 题意: 给你一棵树,你可以任删一条边和加一条边,只要使得其仍然是一棵树,输出每个点是否都能成为重心 题 ...
- CodeForces - 766E (树形dp+二进制)
C - Mahmoud and a xor trip CodeForces - 766E 补题的时候碰见的一道题目,感觉思路非常巧妙就记录下来了. 题目大意:给出n个点,每个点有一个点权,求所有路径的 ...
- Appleman and Tree CodeForces - 461B(树形dp)
Appleman has a tree with n vertices. Some of the vertices (at least one) are colored black and other ...
- codeforces 816 E. Karen and Supermarket(树形dp)
题目链接:http://codeforces.com/contest/816/problem/E 题意:有n件商品,每件有价格ci,优惠券di,对于i>=2,使用di的条件为:xi的优惠券需要被 ...
- Codeforces 1088E Ehab and a component choosing problem(树形DP)
Codeforces 1088E Ehab and a component choosing problem(树形DP) 题意 给一棵树,要求从中选一些联通分量,使得平均联通分量重量总和最大.如果有多 ...
- BZOJ 2133 切割(树形DP,树上背包)大概是本题全网第一篇题解 >_<【BZOJ 修复工程】
整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 BZOJ 2133 切割这道题全网搜不到任何一篇题解 >_< 看评测记录也没有几个人AC- ...
- 【牛客每日一题】4.15 Treepath 题解(树上dfs/树形DP)
题目链接:https://ac.nowcoder.com/acm/problem/14248 来源:牛客网 题目描述 给定一棵n个点的树,问其中有多少条长度为偶数的路径.路径的长度为经过的边的条数.x ...
最新文章
- 高德地图关键字搜索oc版
- Java 启动线程并保持
- JNI与底层调用-2
- 【数据挖掘笔记五】数据立方体技术
- 深圳的中学计算机课学什么时候,2018-2019年深圳中小学校历出炉 中小学校什么时候几号开学...
- Javascript 检测 页面是否在iframe中
- php post调用api,PHP(CURL)POST数据调用API简单示例
- Linux磁盘下面有个mpatha,Linux中如何使用vmstat命令
- 微信小程序的开发需要什么费用
- 计算机碎片整理的作用,经常做磁盘碎片整理的好处
- hangfire安装
- 后台如何暴漏IP用于前后端测试
- igg google
- Kafka设计原理——consumer rebalance概览及过程
- 根据ParentId生成树状结构这po事
- Java 关于中文乱码问题的解决方案与经验【转载】
- Web3 时代 传统品牌如何玩转 NFT 营销?
- Source Insight 4.0安装
- 基于Opencv快速实现人脸识别(图片识别)
- OS基础-四大基本特征
热门文章
- php 取整函数 ceil floor round intval 随笔
- Java线程之CompletionService批处理任务
- 【转载】最好女孩子概率模型
- Javascript -- 二叉树(查找删除功能实现)
- Mr.J---重拾Ajax(一)--XMLHttpRequest
- python基础-python函数参数为print语句时的输出
- Remove Duplicates from Sorted List leetcode
- iOS事件机制,以及不同手势使用touchesBegan等表现形式
- 六步实现Spring.NET 与 NHibernate 的整合
- STL中 set 和 multiset