2016北京集训测试赛(十一)Problem C: 树链问题

Solution
智障暴力题, 每个点维护一下子树信息, 树剖就好了. 我居然还傻了写了一发毛毛虫...
#include <cstdio>
#include <cctype>
#include <vector>
#include <algorithm>
#include <cstring>
#define vector std::vector
#define max std::max
#define min std::min
#define sort std::sort
#define swap std::swap
namespace Zeonfai
{
inline int getInt()
{
int a = 0, sgn = 1; char c;
while(! isdigit(c = getchar())) if(c == '-') sgn *= -1;
while(isdigit(c)) a = a * 10 + c - '0', c = getchar();
return a * sgn;
}
}
const int N = (int)1e5;
int n, m;
int a[N];
struct query
{
int u, v, val;
inline query(int _u, int _v, int _val) {u = _u; v = _v; val = _val;}
};
struct binaryIndexedTree
{
int a[N + 1];
inline void clear() {memset(a, 0, sizeof(a));}
inline void modify(int pos, int x)
{
for(int i = pos; i <= n; i += i & - i) a[i] += x;
}
inline int query(int pos)
{
int res = 0;
for(int i = pos; i; i -= i & - i) res += a[i];
return res;
}
inline int query(int L, int R)
{
if(L > R) return 0; else return query(R) - query(L - 1);
}
}BIT[2];
struct tree
{
struct node
{
vector<int> edg;
int hvy, tp, pre;
int sz, dep;
int id[2], L, R;
vector<query> qry;
int ans;
inline void clear() {edg.clear(); qry.clear();}
}nd[N + 1];
inline void clear() {for(int i = 1; i <= n; ++ i) nd[i].clear();}
inline void addEdge(int u, int v) {nd[u].edg.push_back(v); nd[v].edg.push_back(u);}
void getSize(int u, int pre)
{
nd[u].sz = 1; nd[u].dep = ~ pre ? nd[pre].dep + 1 : 0; nd[u].hvy = -1; nd[u].pre = pre;
for(auto v : nd[u].edg) if(v != pre)
{
getSize(v, u); nd[u].sz += nd[v].sz;
if(nd[u].hvy == -1 || nd[v].sz > nd[nd[u].hvy].sz) nd[u].hvy = v;
}
}
int clk;
void decomposition(int u, int tp)
{
nd[u].tp = tp; nd[u].id[0] = ++ clk;
if(~ nd[u].hvy) decomposition(nd[u].hvy, tp);
for(auto v : nd[u].edg) if(v != nd[u].pre && v != nd[u].hvy) decomposition(v, v);
}
inline void decomposition() {getSize(1, -1); clk = 0; decomposition(1, 1);}
void getSection(int u)
{
if(nd[u].hvy == -1) return;
nd[u].L = (int)1e9; nd[u].R = -1;
for(auto v : nd[u].edg) if(v != nd[u].pre) getSection(v), nd[u].L = min(nd[u].L, nd[v].id[1]), nd[u].R = max(nd[u].R, nd[v].id[1]);
}
inline void getSection() {getSection(1);}
inline int getLCA(int u, int v)
{
while(nd[u].tp != nd[v].tp)
{
if(nd[nd[u].tp].dep > nd[nd[v].tp].dep) u = nd[nd[u].tp].pre;
else if(nd[nd[u].tp].dep < nd[nd[v].tp].dep) v = nd[nd[v].tp].pre;
else u = nd[nd[u].tp].pre, v = nd[nd[v].tp].pre;
}
if(nd[u].dep > nd[v].dep) swap(u, v);
return u;
}
inline int getPath(int u, int v, int opt)
{
int res = 0;
if(opt)
{
if(nd[u].hvy == -1) u = nd[u].pre; if(nd[v].hvy == -1) v = nd[v].pre;
while(nd[u].tp != nd[v].tp)
{
if(nd[nd[u].tp].dep > nd[nd[v].tp].dep) res += BIT[1].query(nd[nd[u].tp].L, nd[u].R), u = nd[nd[u].tp].pre;
else if(nd[nd[u].tp].dep < nd[nd[v].tp].dep) res += BIT[1].query(nd[nd[v].tp].L, nd[v].R), v = nd[nd[v].tp].pre;
else res += BIT[1].query(nd[nd[u].tp].L, nd[u].R) + BIT[1].query(nd[nd[v].tp].L, nd[v].R), u = nd[nd[u].tp].pre, v = nd[nd[v].tp].pre;
}
if(nd[u].dep > nd[v].dep) swap(u, v);
res += BIT[1].query(nd[u].L, nd[v].R);
}
else
{
while(nd[u].tp != nd[v].tp)
{
if(nd[nd[u].tp].dep > nd[nd[v].tp].dep) res += BIT[0].query(nd[nd[u].tp].id[0], nd[u].id[0]), u = nd[nd[u].tp].pre;
else if(nd[nd[u].tp].dep < nd[nd[v].tp].dep) res += BIT[0].query(nd[nd[v].tp].id[0], nd[v].id[0]), v = nd[nd[v].tp].pre;
else res += BIT[0].query(nd[nd[u].tp].id[0], nd[u].id[0]) + BIT[0].query(nd[nd[v].tp].id[0], nd[v].id[0]), u = nd[nd[u].tp].pre, v = nd[nd[v].tp].pre;
}
if(nd[u].dep > nd[v].dep) swap(u, v);
res += BIT[0].query(nd[u].id[0], nd[v].id[0]);
}
return res;
}
int getAnswer(int u)
{
nd[u].ans = 0;
for(auto v : nd[u].edg) if(v != nd[u].pre) nd[u].ans += getAnswer(v);
for(auto qry : nd[u].qry)
{
int cur = qry.val;
cur += getPath(qry.u, qry.v, 1) - getPath(qry.u, qry.v, 0);
nd[u].ans = max(nd[u].ans, cur);
}
for(int i = 0; i < 2; ++ i) BIT[i].modify(nd[u].id[i], nd[u].ans);
return nd[u].ans;
}
inline int getAnswer() {return getAnswer(1);}
}T;
inline int cmp(int a, int b)
{
int preA = T.nd[a].pre, preB = T.nd[b].pre;
if(preA == -1) return 1; else if(preB == -1) return 0; else return T.nd[preA].id[0] < T.nd[preB].id[0];
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("tchain.in", "r", stdin);
freopen("tchain.out", "w", stdout);
#endif
using namespace Zeonfai;
for(int cs = getInt(); cs --;)
{
n = getInt(), m = getInt();
T.clear(); for(int i = 0; i < 2; ++ i) BIT[i].clear();
for(int i = 1; i < n; ++ i)
{
int u = getInt(), v = getInt();
T.addEdge(u, v);
}
T.decomposition();
for(int i = 1; i <= n; ++ i) a[i] = i; sort(a + 1, a + n + 1, cmp); for(int i = 1; i <= n; ++ i) T.nd[a[i]].id[1] = i;
T.getSection();
for(int i = 0; i < m; ++ i)
{
int u = getInt(), v = getInt(), val = getInt();
T.nd[T.getLCA(u, v)].qry.push_back(query(u, v, val));
}
printf("%d\n", T.getAnswer());
}
}
2016北京集训测试赛(十一)Problem C: 树链问题的更多相关文章
- 2016北京集训测试赛(十七)Problem C: 数组
Solution 线段树好题. 我们考虑用last[i]表示\(i\)这个位置的颜色的上一个出现位置. 考虑以一个位置\(R\)为右端点的区间最远能向左延伸到什么位置: \(L = \max_{i \ ...
- 2016北京集训测试赛(十七)Problem B: 银河战舰
Solution 好题, 又是长链剖分2333 考虑怎么统计答案, 我场上的思路是统计以一个点作为结尾的最长上升链, 但这显然是很难处理的. 正解的方法是统计以每个点作为折弯点的最长上升链. 具体的内 ...
- 2016北京集训测试赛(十七)Problem A: crash的游戏
Solution 相当于要你计算这样一个式子: \[ \sum_{x = 0}^m \left( \begin{array}{} m \\ x \end{array} \right) \left( \ ...
- 2016北京集训测试赛(十六)Problem C: ball
Solution 这是一道好题. 考虑球体的体积是怎么计算的: 我们令\(f_k(r)\)表示\(x\)维单位球的体积, 则 \[ f_k(1) = \int_{-1}^1 f_{k - 1}(\sq ...
- 2016北京集训测试赛(十六)Problem B: river
Solution 这题实际上并不是构造题, 而是一道网络流. 我们考虑题目要求的一条路径应该是什么样子的: 它是一个环, 并且满足每个点有且仅有一条出边, 一条入边, 同时这两条边的权值还必须不一样. ...
- 2016北京集训测试赛(十六)Problem A: 任务安排
Solution 这道题告诉我们, 不能看着数据范围来推测正解的时间复杂度. 事实证明, 只要常数足够小, \(5 \times 10^6\)也是可以跑\(O(n \log n)\)算法的!!! 这道 ...
- BZOJ 4543 2016北京集训测试赛(二)Problem B: thr 既 长链剖分学习笔记
Solution 这题的解法很妙啊... 考虑这三个点可能的形态: 令它们的重心为距离到这三个点都相同的节点, 则其中两个点分别在重心的两棵子树中, 且到重心的距离相等; 第三个点可能在重心的一棵不同 ...
- 2016北京集训测试赛(十四)Problem B: 股神小D
Solution 正解是一个\(\log\)的link-cut tree. 将一条边拆成两个事件, 按照事件排序, link-cut tree维护联通块大小即可. link-cut tree维护子树大 ...
- 2016北京集训测试赛(十四)Problem A: 股神小L
Solution 考虑怎么卖最赚钱: 肯定是只卖不买啊(笑) 虽然说上面的想法很扯淡, 但它确实能给我们提供一种思路, 我们能不买就不买; 要买的时候就买最便宜的. 我们用一个优先队列来维护股票的价格 ...
随机推荐
- 二叉树遍历(Java实现)
二叉树遍历(Java实现) 主要是二叉树的遍历,包括递归遍历和非递归遍历 import java.util.ArrayDeque; import java.util.ArrayList; impo ...
- Singleton模式类 【微软面试100题 第七十二题】
题目要求: 实现C++单例模式,即只能生成一个实例的类. 题目分析: 1.一般情况:用构造函数私有化和静态函数实现. 2.如果考虑内存泄露:用智能指针+一般情况方法. 3.如果考虑线程安全:加锁. 代 ...
- poj1111(单身快乐)
...
- 软工实践 - 第十次作业 Alpha 冲刺 (2 / 10)
队名:起床一起肝活队 组长博客:https://www.cnblogs.com/dawnduck/p/9960710.html 作业博客:班级博客本次作业的链接 组员情况 组员1(队长):白晨曦 过去 ...
- mysql错误之2014
error:2014 Commands out of sync; you can't run this command now 这个错误号我也真是醉了. 一直纠结于为什么存储过程执行完,commit操 ...
- [国家集训队][bzoj2038] 小Z的袜子 [莫队]
题面: 传送门 思路: 又是一道标准的莫队处理题目,但是这道题需要一点小改动:求个数变成了求概率 我们思考:每次某种颜色从i个增加到i+1个,符合要求的情况多了多少? 原来的总情况数是i*(i-1)/ ...
- 完美匹配(matching)
完美匹配(matching) 题目描述 给定nn个点,mm条边的无向图G=(V,E)G=(V,E),求出它的完美匹配数量对106+3106+3取模的值. 一个完美匹配可以用一个排列ϕ:V→Vϕ:V→V ...
- BZOJ3203 保护出题人(defend)
保护出题人(defend) 题目描述 输入 第一行两个空格隔开的正整数n和d,分别表示关数和相邻僵尸间的距离. 接下来n行每行两个空格隔开的正整数,第i + 1行为 a i和 x i,分别表示相比上一 ...
- iOS-app发布证书和调试证书配置
iOS-app发布证书.真机调试证书.测试证书.推送证书详细过程 更重要的是让你彻底明白为什么要这样配置证书 说句废话:凡事当你弄清楚为什么时,就揭开了它复杂和神秘的面纱 正文开始 一:发布证书 遵旨 ...
- LoadRunner中请求HTTPS页面。
哎,真是服了.国内网站上写的解决方法如此的粗糙. 如果用loadrunner访问HTTPS网页时出现:shut connection during attempt to negotiate SSL s ...