HDU 3966 Aragorn's Story(树链剖分)
来源:互联网 发布:高端 商务礼品 知乎 编辑:程序博客网 时间:2024/06/16 01:02
好久没有打线段树了。。
题意
更新树上的一段路径,查询某个点/路径的权值
思路
树链剖分模版题,树链剖分将一棵树转化成多条重链,将树的问题变成区间问题
如图,加粗的是重链,打红点的是链的根节点
代码
#include <bits/stdc++.h>#define mem(a,b) memset(a,b,sizeof(a))#define rep(i,a,b) for(int i=a;i<b;i++)const int INF = 0x3f3f3f3f;const int maxn = 5e4 + 50;const int mod = 1e9 + 7;const double eps = 1e-8;typedef long long ll;using namespace std;struct SegmentTree;struct Edge { int u, v; Edge() {} Edge(int u, int v) : u(u), v(v) {}};//第一遍DFS找出所有重边//重边:连接最大子树的边//第二遍DFS连接重链struct TreePartition { vector<Edge> edges; vector<int> G[maxn]; int siz[maxn]; //子树节点个数 int top[maxn]; //链顶端节点 int son[maxn]; //重儿子 int dep[maxn]; //深度 int tid[maxn]; //剖分后编号 int rnk[maxn];//节点在线段树中的位置 int fa[maxn]; // 父节点 int n, m; int tim; void init(int n) { this->n = n; edges.clear(); rep(i, 0, n + 1) G[i].clear(); mem(son, -1); tim = 0; } void addEdge(int u, int v) { edges.push_back(Edge(u, v)); m = edges.size(); G[u].push_back(m - 1); } void dfs1(int u, int pa, int depth) { dep[u] = depth; fa[u] = pa; siz[u] = 1; int sz = G[u].size(); for (int i = 0; i<sz; i++) { Edge &e = edges[G[u][i]]; int v = e.v; if (v != pa) { dfs1(v, u, depth + 1); siz[u] += siz[v]; if (son[u] == -1 || siz[v]>siz[son[u]]) son[u] = v; } } } void dfs2(int u, int tp) { top[u] = tp; tid[u] = ++tim; rnk[tid[u]] = u; if (son[u] == -1) return; dfs2(son[u], tp); int sz = G[u].size(); for (int i = 0; i<sz; i++) { Edge &e = edges[G[u][i]]; int v = e.v; if (v != son[u] && v != fa[u]) dfs2(v, v); } } void build(int rt) { dfs1(rt, -1, 0); dfs2(rt, rt); }};#define lson(x) (x<<1)#define rson(x) (x<<1|1)#define lhs l,m,lson(rt)#define rhs m+1,r,rson(rt)int s[maxn];struct SegmentTree { int sum[maxn << 2], mark[maxn << 2]; inline void pushUp(int rt) { sum[rt] = sum[lson(rt)] + sum[rson(rt)]; } inline void pushDown(int rt, int len) { if (mark[rt]) { mark[lson(rt)] += mark[rt]; mark[rson(rt)] += mark[rt]; sum[lson(rt)] += mark[rt] * (len - len / 2); sum[rson(rt)] += mark[rt] * (len / 2); mark[rt] = 0; } } void build(int l, int r, int rt) { mark[rt] = 0; if (l == r) sum[rt] = s[l]; else { int m = (l + r) >> 1; build(lhs); build(rhs); pushUp(rt); } } void update(int L, int R, int add, int l, int r, int rt) { int len = r - l + 1; if (L <= l && R >= r) { mark[rt] += add; sum[rt] += (ll)add*len; return; } pushDown(rt, len); int m = (l + r) >> 1; if (L <= m) update(L, R, add, lhs); if (R>m) update(L, R, add, rhs); pushUp(rt); } int query(int L, int R, int l, int r, int rt) { if (L <= l && R >= r) return sum[rt]; pushDown(rt, r - l + 1); int m = (l + r) >> 1; int ret = 0; if (L <= m) ret += query(L, R, lhs); if (R>m) ret += query(L, R, rhs); return ret; }};SegmentTree st;TreePartition tp;int n, m, q;//更新链,查询点/链void changeLine(int x, int y, int add) { while (tp.top[x] != tp.top[y]) { if (tp.dep[tp.top[x]]<tp.dep[tp.top[y]]) swap(x, y); st.update(tp.tid[tp.top[x]], tp.tid[x], add, 1, n, 1); x = tp.fa[tp.top[x]]; } if (tp.dep[x]>tp.dep[y]) swap(x, y); st.update(tp.tid[x], tp.tid[y], add, 1, n, 1);}int ts[maxn];int main(){#ifndef ONLINE_JUDGE //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout);#endif while (~scanf("%d %d %d", &n, &m, &q)) { rep(i, 1, n + 1) scanf("%d", &ts[i]); tp.init(n); int u, v; char buf[10]; rep(i, 0, m) { scanf("%d %d", &u, &v); tp.addEdge(u, v); tp.addEdge(v, u); } tp.build(1); //Important!! rep(i, 1, n + 1) s[i] = ts[tp.rnk[i]]; st.build(1, n, 1); scanf("%d", &q); rep(i, 0, q) { scanf(" %s", buf); if (buf[0] != 'Q') { int add; scanf("%d %d %d", &u, &v, &add); if (buf[0] == 'D') add = -add; changeLine(u, v, add); } else { scanf("%d", &u); printf("%d\n", st.query(tp.tid[u], tp.tid[u], 1, n, 1)); } } } return 0;}
0 0
- HDU 3966 Aragorn's Story 树链剖分模板
- hdu 3966 Aragorn's Story(树链剖分)
- hdu 3966 Aragorn's Story (树链剖分)
- hdu 3966 Aragorn's Story 树链剖分
- Hdu 3966 Aragorn's Story (树链剖分)
- 【HDU】3966 Aragorn's Story 树链剖分
- HDU 3966 Aragorn's Story 树链剖分
- HDU 3966 Aragorn's Story(树链剖分)
- hdu 3966 Aragorn's Story 树链剖分
- HDU 3966 Aragorn's Story --树链剖分
- HDU 3966 Aragorn's Story (树链剖分)
- HDU 3966 Aragorn's Story(树链剖分)
- [HDU 3966] Aragorn's Story 树链剖分
- HDU 3966 Aragorn's Story(树链剖分)
- HDU 3966 Aragorn's Story 树链剖分
- HDU 3966 Aragorn's Story(树链剖分)
- HDU 3966 Aragorn's Story(树链剖分)
- HDU 3966 - Aragorn's Story(树链剖分)
- Android清单注册总结
- Windows上C++使用命名管道进行进程间通讯
- ajax 每10秒调用一次接口
- 一个小算法的优化
- JSONArray与Java对象之间的转换
- HDU 3966 Aragorn's Story(树链剖分)
- KMP算法
- Python之inspect模块实现获取加载模块路径
- 运算符
- 实现数据库与项目的链接
- makefile调试技巧1
- 【Hotspot】tomcat参数调整
- 自己编写的shell脚本开机运行
- nyoj 891 找点