题意:要求在一棵N(<=50000)个带权节点的树上支持3种操作

(1)I u v w,u到v的路径上每个节点权值增加w

(2)D u v w,u到v的路径上每个节点权值减少w

(3)Q u,求u点的权值

思路:

将树剖分成若干条链,然后用区间数据结构来维护,这就是树链剖分。树链剖分后,这个题可以转化为一个“区间修改,单点查询”的问题,树状数组或线段树即可。

树状数组(1100ms):

#pragma comment(linker, "/STACK:10240000,10240000")#include <iostream>
#include <cstdio>
#include <ctime>
#include <cstring>
using namespace std;
#define X first
#define Y second
#define pb(x) push_back(x)
#define mp(x, y) make_pair(x, y)
#define all(a) (a).begin(), (a).end()
#define mset(a, x) memset(a, x, sizeof(a))
#define mcpy(a, b) memcpy(a, b, sizeof(b))
#define cas() int T, cas = 0; cin >> T; while (T --)
template<typename T>bool umax(T&a, const T&b){return a<b?(a=b,true):false;}
template<typename T>bool umin(T&a, const T&b){return b<a?(a=b,true):false;}
typedef long long ll;
typedef pair<int, int> pii;#ifndef ONLINE_JUDGE#include "local.h"
#endifconst int N = 5e4 + 7;
const int M = N;namespace Edge {int last[N], to[M << 1], next[M << 1], cntE;void init() {cntE = 0;memset(last, -1, sizeof(last));}void addEdge(int u, int v) {to[cntE] = v;next[cntE] = last[u];last[u] = cntE ++;}
}namespace TreeChain {int dep[N], top[N], w[N], son[N], siz[N], fa[N];int id[N], rnk[N], cntID;void init() {cntID = 0;memset(son, -1, sizeof(son));}void dfs1(int u, int f, int d) {dep[u] = d;fa[u] = f;siz[u] = 1;for (int i = Edge::last[u]; ~i; i = Edge::next[i]) {int v = Edge::to[i];if (v != f) {dfs1(v, u, d + 1);siz[u] += siz[v];if (son[u] == -1 || siz[v] > siz[son[u]])son[u] = v;}}}void dfs2(int u, int t) {top[u] = t;id[u] = ++ cntID;rnk[id[u]] = u;if (son[u] == -1) return;dfs2(son[u], t);for (int i = Edge::last[u]; ~i; i = Edge::next[i]) {int v = Edge::to[i];if (v != son[u] && v != fa[u])dfs2(v, v);}}
}int a[N];namespace TreeArray {int c[N], n;void init(int n) {memset(c, 0, sizeof(c));TreeArray::n = n;}int lowbit(int x) { return x & -x; }void add(int p, int x) {while (p <= n) {c[p] += x;p += lowbit(p);}}void add(int l, int r, int x) {add(l, x);add(r + 1, -x);}int query(int p) {int ans = 0;while (p) {ans += c[p];p -= lowbit(p);}return ans;}void change(int u, int v, int w) {using namespace TreeChain;while (top[u] != top[v]) {if (dep[top[u]] < dep[top[v]]) swap(u, v);add(id[top[u]], id[u], w);u = fa[top[u]];}if (dep[u] > dep[v]) swap(u, v);add(id[u], id[v], w);}
}int main() {
#ifndef ONLINE_JUDGEfreopen("in.txt", "r", stdin);//freopen("out.txt", "w", stdout);
#endif // ONLINE_JUDGEint n, m, p, u, v, w;char s[2];while (cin >> n >> m >> p) {Edge::init();TreeChain::init();for (int i = 1; i <= n; i ++) {scanf("%d", a + i);}for (int i = 0; i < m; i ++) {scanf("%d%d", &u, &v);Edge::addEdge(u, v);Edge::addEdge(v, u);}TreeChain::dfs1(1, 0, 0);TreeChain::dfs2(1, 1);TreeArray::init(n);for (int i = 1; i <= n; i ++) {TreeArray::add(i, i, a[TreeChain::rnk[i]]);}for (int i = 0; i < p; i ++) {scanf("%s", s);if (*s == 'Q') {scanf("%d", &u);printf("%d\n", TreeArray::query(TreeChain::id[u]));}else {scanf("%d%d%d", &u, &v, &w);if (*s == 'D') w = -w;TreeArray::change(u, v, w);}}}return 0;
}

线段树(1900ms):

#pragma comment(linker, "/STACK:10240000,10240000")#include <iostream>
#include <cstdio>
#include <ctime>
#include <cstring>
using namespace std;
#define X first
#define Y second
#define pb(x) push_back(x)
#define mp(x, y) make_pair(x, y)
#define all(a) (a).begin(), (a).end()
#define mset(a, x) memset(a, x, sizeof(a))
#define mcpy(a, b) memcpy(a, b, sizeof(b))
#define cas() int T, cas = 0; cin >> T; while (T --)
template<typename T>bool umax(T&a, const T&b){return a<b?(a=b,true):false;}
template<typename T>bool umin(T&a, const T&b){return b<a?(a=b,true):false;}
typedef long long ll;
typedef pair<int, int> pii;#ifndef ONLINE_JUDGE#include "local.h"
#endifconst int N = 5e4 + 7;
const int M = N;namespace Edge {int last[N], to[M << 1], next[M << 1], cntE;void init() {cntE = 0;memset(last, -1, sizeof(last));}void addEdge(int u, int v) {to[cntE] = v;next[cntE] = last[u];last[u] = cntE ++;}
}namespace TreeChain {int dep[N], top[N], w[N], son[N], siz[N], fa[N];int id[N], rnk[N], cntID;void init() {cntID = 0;memset(son, -1, sizeof(son));}void dfs1(int u, int f, int d) {dep[u] = d;fa[u] = f;siz[u] = 1;for (int i = Edge::last[u]; ~i; i = Edge::next[i]) {int v = Edge::to[i];if (v != f) {dfs1(v, u, d + 1);siz[u] += siz[v];if (son[u] == -1 || siz[v] > siz[son[u]])son[u] = v;}}}void dfs2(int u, int t) {top[u] = t;id[u] = ++ cntID;rnk[id[u]] = u;if (son[u] == -1) return;dfs2(son[u], t);for (int i = Edge::last[u]; ~i; i = Edge::next[i]) {int v = Edge::to[i];if (v != son[u] && v != fa[u])dfs2(v, v);}}
}int a[N];namespace SegTree {#define lson l, m, rt << 1#define rson m + 1, r, rt << 1 | 1int sum[N << 2], mark[N << 2];void up(int rt) {sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];}void down(int rt, int len) {int rlen = len >> 1, llen = len - rlen;if (mark[rt]) {sum[rt << 1] += llen * mark[rt];mark[rt << 1] += mark[rt];sum[rt << 1 | 1] += rlen * mark[rt];mark[rt << 1 | 1] += mark[rt];mark[rt] = 0;}}void build(int l, int r, int rt) {mark[rt] = 0;if (l == r) {sum[rt] = a[TreeChain::rnk[l]];return;}int m = (l + r) >> 1;build(lson);build(rson);up(rt);}void update(int L, int R, int x, int l, int r, int rt) {if (L <= l && r <= R) {sum[rt] += (r - l + 1) * x;mark[rt] += x;return;}int m = (l + r) >> 1;down(rt, r - l + 1);if (L <= m) update(L, R, x, lson);if (R > m) update(L, R, x, rson);up(rt);}int query(int p, int l, int r, int rt) {if (l == r) return sum[rt];int m = (l + r) >> 1;down(rt, r - l + 1);if (p <= m) return query(p, lson);else return query(p, rson);}void change(int u, int v, int w, int n) {using namespace TreeChain;while (top[u] != top[v]) {if (dep[top[u]] < dep[top[v]]) swap(u, v);update(id[top[u]], id[u], w, 1, n, 1);u = fa[top[u]];}if (dep[u] > dep[v]) swap(u, v);update(id[u], id[v], w, 1, n, 1);}#undef lson#undef rson
}int main() {
#ifndef ONLINE_JUDGEfreopen("in.txt", "r", stdin);//freopen("out.txt", "w", stdout);
#endif // ONLINE_JUDGEint n, m, p, u, v, w;char s[2];while (cin >> n >> m >> p) {Edge::init();TreeChain::init();for (int i = 1; i <= n; i ++) {scanf("%d", a + i);}for (int i = 0; i < m; i ++) {scanf("%d%d", &u, &v);Edge::addEdge(u, v);Edge::addEdge(v, u);}TreeChain::dfs1(1, 0, 0);TreeChain::dfs2(1, 1);SegTree::build(1, n, 1);for (int i = 0; i < p; i ++) {scanf("%s", s);if (*s == 'Q') {scanf("%d", &u);printf("%d\n", SegTree::query(TreeChain::id[u], 1, n, 1));}else {scanf("%d%d%d", &u, &v, &w);if (*s == 'D') w = -w;SegTree::change(u, v, w, n);}}}return 0;
}

  

转载于:https://www.cnblogs.com/jklongint/p/4950641.html

[hdu3966 Aragorn's Story]树链剖分相关推荐

  1. HDU - 3966 Aragorn's Story(树链剖分+线段树)

    题目链接:点击查看 题目大意:给出一棵由n个点组成的树,每个点都有一个权值,接下来有k次操作,每次操作分为下面几种类型: I u v x:将u-v这条路径上的所有点权值加上x D u v x:将u-v ...

  2. HDU - 3966 Aragorn's Story(树链剖分)

    题目传送门:HDU - 3966 Aragorn's Story 题目大意: 存在一个树,树上每个节点为一个阵营,阵营中存在敌人,现在要进行以下操作 I  C1  C2  K :将阵营C1到阵营C2路 ...

  3. HDU3966(树链剖分)

    题目:Aragorn's Story 题意:给一棵树,并给定各个点权的值,然后有3种操作: I C1 C2 K: 把C1与C2的路径上的所有点权值加上K D C1 C2 K:把C1与C2的路径上的所有 ...

  4. HDU 3966 Aragorn's Story (树链点权剖分,成段修改单点查询)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3966 树链剖分的模版,成段更新单点查询.熟悉线段树的成段更新的话就小case啦. 1 //树链剖分 边 ...

  5. HDU 3966 Aragorn's Story (树链剖分+线段树)

    题意:给你一棵树,然后有三种操作 I L R K: 把L与R的路径上的所有点权值加上K D L R K:把L与R的路径上的所有点权值减去K Q X:查询节点编号为X的权值 思路:树链剖分裸题(我还没有 ...

  6. SPOJ375(树链剖分)

    题目:Query on a tree 题意:给定一棵树,告诉了每条边的权值,然后给出两种操作: (1)把第i条边的权值改为val (2)询问a,b路径上权值最大的边 分析:本题与HDU3966差不多, ...

  7. SPOJ- QTREE+HDU 3966(树链剖分裸题

    题目:维护一个树,支持修改边长,查询任意两点间距离. 思路:学习了一下树链剖分,还是看了一阵子才看懂的(大概两个多小时orz...)其实总的来说并不是很难,主要是数组比较多,然后看的那篇博客大概是为了 ...

  8. 树链剖分 讲解+模板+习题

    今天我们来讲一下树链剖分 树链剖分是什么? 树链剖分是一种用来维护树上路径信息的在线方法,可以处理在线. 通常通过一种方法,将一棵树剖分成若干条链,然后通过数据结构(线段树,BIT等)去维护. 我们通 ...

  9. 树链剖分入门——[kuangbin]树链剖分

    树链剖分的本质就是将一棵树拆分成一段一段连续的区间,然后放在一起就可以用一棵单独的线段树处理区间问题,只需要将树上节点和线段树节点的对应关系求好就可以很方便的互相转换,而树上两点之间路径的相关问题就可 ...

最新文章

  1. PetaPoco 使用总结(二)
  2. vs 启动调用的目标发生异常_如何解决不可测、异常场景的问题?
  3. HTML5 webfont字体图标的使用
  4. python之路——面向对象进阶
  5. zabbix监控操纵系统日志
  6. VS2013 堆栈溢出调查(0xC00000FD: Stack overflow)
  7. PB实现URL模式及MIME模式的BASE64加解密
  8. 设计师经常逛的色彩搭配网站—配色方案吧
  9. wps序号打乱重新排序_WPS中Excel怎么自动排序
  10. 能搬砖的游戏有哪些,有哪些比较适合新手去做?
  11. 6款沙发背景墙装饰画 总有一幅你喜欢的
  12. 《雪鹰领主3D》昨日腾讯玩吧首发! HTML5进入3D游戏时代!
  13. 阿里、字节跳动再度发力游戏,腾讯、网易怕了吗?
  14. 斐讯n1遥控器app(支持休眠和唤醒)——WiFi篇
  15. python车辆定位调度管理系统,基于django+twisted
  16. Pose for Everything: Towards Category-Agnostic Pose Estimation 阅读笔记
  17. linux ln 软连接_ln命令建立软链接
  18. 前端如何做好SEO优化
  19. 本科准程序员如何才能进入腾讯,阿里等一流的互联网公司?
  20. java list高效去重_简述Java List去重五种方法

热门文章

  1. App Builder 2020中文版
  2. 试试 python-dotenv,避免敏感信息被硬编码到代码中
  3. 特征筛选(随机森林)
  4. vue1与vue2的路由 以及vue2项目大概了解
  5. iOS - Quartz 2D 画板绘制
  6. 关于return和exit
  7. javascript操作对象的方法
  8. UITableView 学习笔记
  9. Linux:编译动态库时遇到的错误relocation R_X86_64_32 against `a local symbol'
  10. cocos2dx 自定义动画