博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[bzoj3531][Sdoi2014]旅行
阅读量:5296 次
发布时间:2019-06-14

本文共 3686 字,大约阅读时间需要 12 分钟。

题目大意:给你一棵树,每个点有一个分类和一个值。有四种操作:

  1. 修改某个点的分类
  2. 修改某个点的值
  3. 查询两个分类相同的点的最短路上,与这两个点分类相同的所有点的值的和
  4. 查询两个分类相同的点的最短路上,与这两个点分类相同的所有点的值的最大值

题解:树链剖分,对每一个分类建一棵动态开点线段树就好了。

卡点:1.询问是传根写成了传编号

 

C++ Code:

#include 
#define maxn 100010#define N 100010 * 4 * 20using namespace std;int n, Q;int w[maxn], c[maxn];inline int max(int a, int b) {return a > b ? a : b;}inline void swap(int &a, int &b) {a ^= b ^= a ^= b;}int head[maxn], cnt;struct Edge { int to, nxt;} e[maxn << 1];void add(int a, int b) { e[++cnt] = (Edge) {b, head[a]}; head[a] = cnt;}int sz[maxn], fa[maxn], dep[maxn], son[maxn];int top[maxn], dfn[maxn], idx;void dfs1(int rt) { sz[rt] = 1; for (int i = head[rt]; i; i = e[i].nxt) { int v = e[i].to; if (!dep[v]) { dep[v] = dep[rt] + 1; fa[v] = rt; dfs1(v); sz[rt] += sz[v]; if (!son[rt] || sz[v] > sz[son[rt]]) son[rt] = v; } }}void dfs2(int rt) { dfn[rt] = ++idx; int v = son[rt]; if (v) top[v] = top[rt], dfs2(v); for (int i = head[rt]; i; i = e[i].nxt) { v = e[i].to; if (v != fa[rt] && v != son[rt]) { top[v] = v; dfs2(v); } }}int root[maxn], M[N], S[N];int rc[N], lc[N], tot;void add(int &rt, int l, int r, int p, int num) { if (!rt) rt = ++tot; if (l == r) { S[rt] = M[rt] = num; return ; } int mid = l + r >> 1; if (p <= mid) add(lc[rt], l, mid, p, num); else add(rc[rt], mid + 1, r, p, num); M[rt] = max(M[lc[rt]], M[rc[rt]]); S[rt] = S[lc[rt]] + S[rc[rt]];}int askM(int rt, int l, int r, int L, int R) { if (!rt || l > r || L > R) return 0; if (L <= l && R >= r) return M[rt]; int mid = l + r >> 1, ans = 0; if (L <= mid) ans = askM(lc[rt], l, mid, L, R); if (R > mid) ans = max(ans, askM(rc[rt], mid + 1, r, L, R)); return ans;}int askS(int rt, int l, int r, int L, int R) { if (!rt || l > r || L > R) return 0; if (L <= l && R >= r) return S[rt]; int mid = l + r >> 1, ans = 0; if (L <= mid) ans = askS(lc[rt], l, mid, L, R); if (R > mid) ans += askS(rc[rt], mid + 1, r, L, R); return ans;}int queryM(int rt, int x, int y) { int ans = 0; while (top[x] != top[y]) { if (dep[top[x]] < dep[top[y]]) swap(x, y); ans = max(ans, askM(rt, 1, n, dfn[top[x]], dfn[x])); x = fa[top[x]]; } if (dep[x] > dep[y]) swap(x, y); ans = max(ans, askM(rt, 1, n, dfn[x], dfn[y])); return ans;}int queryS(int rt, int x, int y) { int ans = 0; while (top[x] != top[y]) { if (dep[top[x]] < dep[top[y]]) swap(x, y); ans += askS(rt, 1, n, dfn[top[x]], dfn[x]); x = fa[top[x]]; } if (dep[x] > dep[y]) swap(x, y); ans += askS(rt, 1, n, dfn[x], dfn[y]); return ans;}int main() { scanf("%d%d", &n, &Q); for (int i = 1; i <= n; i++) scanf("%d%d", &w[i], &c[i]); for (int i = 1; i < n; i++) { int a, b; scanf("%d%d", &a, &b); add(a, b); add(b, a); } dep[top[1] = 1] = 1; dfs1(1); dfs2(1); for (int i = 1; i <= n; i++) add(root[c[i]], 1, n, dfn[i], w[i]); while (Q --> 0) { char op[10]; int x, y; scanf("%s%d%d", op, &x, &y); if (op[1] == 'C') { add(root[c[x]], 1, n, dfn[x], 0); c[x] = y; add(root[y], 1, n, dfn[x], w[x]); } if (op[1] == 'W') { w[x] = y; add(root[c[x]], 1, n, dfn[x], y); } if (op[1] == 'S') { printf("%d\n", queryS(root[c[x]], x, y)); } if (op[1] == 'M') { printf("%d\n", queryM(root[c[x]], x, y)); } } return 0;}

  

转载于:https://www.cnblogs.com/Memory-of-winter/p/9493466.html

你可能感兴趣的文章
BZOJ1916: [Usaco2010 Open]冲浪
查看>>
CodeforcesD. Aztec Catacombs
查看>>
learning webrtc 使用node.js
查看>>
BFC 形成条件
查看>>
天坑之mysql乱码问题以及mysql重启出现1067的错误解决
查看>>
iOS-获取当前View所在的控制器
查看>>
LUIS Entities 分类
查看>>
虚拟内存
查看>>
我排第几个(康托展开)
查看>>
Linux 系统性能:观察、测试、调优
查看>>
JS跳出框架返回上一页
查看>>
vue+django2.0.2-rest-framework 生鲜项目(七)
查看>>
虚拟机win7 自动休眠
查看>>
Qt事件系统之一:Qt中的事件处理与传递
查看>>
layui数据表格使用(一:基础篇,数据展示、分页组件、表格内嵌表单和图片)...
查看>>
Django框架学习
查看>>
云片网短信发送
查看>>
(转)FP-tree的hadoop实现
查看>>
GC+JVM
查看>>
BZOJ2330: [SCOI2011]糖果
查看>>