BZOJ 3531 SDOI2014 旅行(travel) 树链剖分模板题
来源:互联网 发布:杰科网络电视机顶盒r1 编辑:程序博客网 时间:2024/04/30 15:54
题目大意
给你一个有
现在有
宗教数小于100000 评价值小于10000
解题思路
用树链剖分为先预处理原树,再用线段树维链剖的最大值和权值和。每次找城市
程序
//SDOI2014 旅行(travel) YxuanwKeith#include <cstring>#include <cstdio>#include <algorithm>using namespace std;const int MAXN = 2e5 + 5, MAXL = 17;struct Tree { int Max, Sum, l, r;} Tr[MAXN * MAXL];int N, M, tot, Val[MAXN], Bel[MAXN], Last[MAXN], Go[MAXN], Next[MAXN];int Num, Cnt, Root[MAXN], Size[MAXN], Ord[MAXN], Top[MAXN], Mson[MAXN], Deep[MAXN], Fa[MAXN][MAXL + 1];void Link(int u, int v) { Next[++ tot] = Last[u], Last[u] = tot, Go[tot] = v;}void Basis(int Now, int fa) { Size[Now] = 1, Fa[Now][0] = fa, Deep[Now] = Deep[fa] + 1; for (int p = Last[Now]; p; p = Next[p]) { int v = Go[p]; if (v == fa) continue; Basis(v, Now); Size[Now] += Size[v]; if (Size[Mson[Now]] < Size[v]) Mson[Now] = v; }}void GetFa() { for (int i = 1; i <= MAXL; i ++) for (int j = 1; j <= N; j ++) Fa[j][i] = Fa[Fa[j][i - 1]][i - 1];}void Promote(int Now, int top) { if (!Now) return; Ord[Now] = ++ Num, Top[Now] = top; Promote(Mson[Now], top); for (int p = Last[Now]; p; p = Next[p]) { int v = Go[p]; if (v == Fa[Now][0] || v == Mson[Now]) continue; Promote(v, v); }}int Lca(int x, int y) { if (Deep[x] < Deep[y]) swap(x, y); for (int i = MAXL; i + 1; i --) if (Deep[Fa[x][i]] >= Deep[y]) x = Fa[x][i]; if (x == y) return x; for (int i = MAXL; i + 1; i --) if (Fa[x][i] != Fa[y][i]) x = Fa[x][i], y = Fa[y][i]; return Fa[x][0];}void Update(int Now) { int l = Tr[Now].l, r = Tr[Now].r; Tr[Now].Max = max(Tr[l].Max, Tr[r].Max); Tr[Now].Sum = Tr[l].Sum + Tr[r].Sum;} void Modify(int &Now, int l, int r, int Num, int Val) { if (!Now) Now = ++ Cnt; if (l == r) { Tr[Now].Max = Tr[Now].Sum = Val; return; } int Mid = (l + r) >> 1; if (Num <= Mid) Modify(Tr[Now].l, l, Mid, Num, Val); else Modify(Tr[Now].r, Mid + 1, r, Num, Val); Update(Now);}int QueryS(int Now, int l, int r, int lx, int rx) { if (!Now) return 0; if (l == lx && r == rx) return Tr[Now].Sum; int Mid = (l + r) >> 1, L = Tr[Now].l, R = Tr[Now].r; if (rx <= Mid) return QueryS(L, l, Mid, lx, rx); else if (lx > Mid) return QueryS(R, Mid + 1, r, lx, rx); else return QueryS(L, l, Mid, lx, Mid) + QueryS(R, Mid + 1, r, Mid + 1, rx);}int QueryM(int Now, int l, int r, int lx, int rx) { if (!Now) return 0; if (l == lx && r == rx) return Tr[Now].Max; int Mid = (l + r) >> 1, L = Tr[Now].l, R = Tr[Now].r; if (rx <= Mid) return QueryM(L, l, Mid, lx, rx); else if (lx > Mid) return QueryM(R, Mid + 1, r, lx, rx); else return max(QueryM(L, l, Mid, lx, Mid), QueryM(R, Mid + 1, r, Mid + 1, rx));}void TreeChain() { Basis(1, 0), Promote(1, 1); GetFa(); for (int i = 1; i <= N; i ++) Modify(Root[Bel[i]], 1, N, Ord[i], Val[i]);}int SolveSum(int ord, int u, int v) { int Sum = 0; for (; Top[u] != Top[v]; u = Fa[Top[u]][0]) Sum += QueryS(Root[ord], 1, N, Ord[Top[u]], Ord[u]); Sum += QueryS(Root[ord], 1, N, Ord[v], Ord[u]); return Sum;}int SolveMax(int ord, int u, int v) { int Max = 0; for (; Top[u] != Top[v] ; u = Fa[Top[u]][0]) Max = max(Max, QueryM(Root[ord], 1, N, Ord[Top[u]], Ord[u])); Max = max(Max, QueryM(Root[ord], 1, N, Ord[v], Ord[u])); return Max;}void GetSum(int u, int v) { int lca = Lca(u, v); int Ans = SolveSum(Bel[u], u, lca) + SolveSum(Bel[u], v, lca); if (Bel[u] == Bel[lca]) Ans -= Val[lca]; printf("%d\n", Ans);}void GetMax(int u, int v) { int lca = Lca(u, v); printf("%d\n", max(SolveMax(Bel[u], u, lca), SolveMax(Bel[u], v, lca)));}int main() { freopen("travel.in", "r", stdin), freopen("travel.out", "w", stdout); scanf("%d%d", &N, &M); for (int i = 1; i <= N; i ++) scanf("%d%d", &Val[i], &Bel[i]); for (int i = 1; i < N; i ++) { int u, v; scanf("%d%d", &u, &v); Link(u, v), Link(v, u); } TreeChain(); for (int i = 1; i <= M; i ++) { char C[2]; int u, v; scanf("%s%d%d", C, &u, &v); if (C[1] == 'W') Val[u] = v, Modify(Root[Bel[u]], 1, N, Ord[u], v); if (C[0] == 'C' && C[1] == 'C') { Modify(Root[Bel[u]], 1, N, Ord[u], 0); Bel[u] = v; Modify(Root[Bel[u]], 1, N, Ord[u], Val[u]); } if (C[1] == 'M') GetMax(u, v); if (C[0] == 'Q' && C[1] == 'S') GetSum(u, v); }}
2 0
- BZOJ 3531 SDOI2014 旅行(travel) 树链剖分模板题
- BZOJ 3531 SDOI2014 旅行 树链剖分
- bzoj 3531: [Sdoi2014]旅行 树链剖分
- BZOJ 3531 [Sdoi2014]旅行 树链剖分
- BZOJ 3531: [Sdoi2014]旅行
- 【BZOJ 3531】 [Sdoi2014]旅行
- [bzoj 3531]sdoi2014 旅行
- bzoj 3531 [SDOI2014]旅行
- bzoj 3531: [Sdoi2014]旅行
- [树链剖分 线段树] BZOJ 3531 [Sdoi2014]旅行
- 【bzoj 3531】 [Sdoi2014]旅行(树链剖分+树套树)
- BZOJ 3531 [SDOI2014]旅行 树链剖分+线段树
- bzoj 3531: [Sdoi2014]旅行 线段树+树链剖分
- BZOJ 3531 [Sdoi2014]旅行 树链剖分 线段树
- |BZOJ 3531|树链剖分|动态开点线段树|[Sdoi2014]旅行
- 【BZOJ】【P3531】【SDOI2014】【旅行】【题解】【树链剖分】
- bzoj P3531 [Sdoi2014]旅行
- 【jzoj3625】【SDOI2014】【旅行(travel)】 【虚树】【lct】
- 《数据结构》 循环链表和双向链表常用操作代码集合
- jQuery学习笔记——选择器2
- IT行业导览-第3章-相关职位
- 公有的、私有的、受保护的继承
- 3998: [TJOI2015]弦论 后缀自动机
- BZOJ 3531 SDOI2014 旅行(travel) 树链剖分模板题
- Observable和Observer
- 全排列 枚举
- VC6.0 fatal error C1853: 'Debug/xx.pch' is not a precompiled header
- hdu5014——构造打表找规律
- Android Toast的学习与简单应用
- 解决Android中的SQLite数据库并发访问
- Mac下Cornerstone无法查看SVN日志的问题的解决办法
- Java——JDOM方式生成XML