博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
树链剖分+线段树 HDOJ 4897 Little Devil I(小恶魔)
阅读量:6142 次
发布时间:2019-06-21

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

 

题意:

  给定一棵树,每条边有黑白两种颜色,初始都是白色,现在有三种操作:

    1 u v:u到v路径(最短)上的边都取成相反的颜色

    2 u v:u到v路径上相邻的边都取成相反的颜色(相邻即仅有一个节点在路径上)

    3 u v:查询u到v路径上有多少个黑色边

思路:

  对树进行树链剖分,分成重链和轻链,用两棵线段树W,L来维护。W维护树上在重链上的u和v之间的边的翻转情况(操作在线段树上的[pos[v],pos[u]]区间);L维护树上在重链上的u和v之间的相邻边的翻转情况。那么某一个点u与它父亲节点fa[u]的边的最终翻转情况为:W(pos[u], pos[u])(如果边是重链上的边),W(pos[u], pos[u])^L(pos[fa[u]], pos[fa[u]])(如果边是轻链)。对于1操作,只要简单的在W上维护就可以了。对于2操作,除了在L上操作,还要注意头和尾的特殊处理(因为对于重链内的点,不包括头尾,只在W上查询),也就是u的重链上的儿子son[u]以及u的链头p=belong[u]要在W上翻转一次,结合图可能更能理解。还有就是线段树的操作了。

 

另外:

  u可能没有son[u],默认为虚点0,那么在线段树上需要加上一句话:if (l == r) return ;

#include 
const int N = 1e5 + 5;//线段树#define lson l, mid, o << 1#define rson mid + 1, r, o << 1 | 1struct Seg_Tree { int fp[N<<2], s[N<<2]; void flip(int l, int r, int o) { s[o] = (r - l + 1) - s[o]; fp[o] ^= 1; } void push_up(int o) { s[o] = s[o<<1] + s[o<<1|1]; } void push_down(int l, int r, int o) { if (fp[o]) { int mid = l + r >> 1; flip (lson); flip (rson); fp[o] = 0; } } void build(int l, int r, int o) { fp[o] = s[o] = 0; if (l == r) { return ; } int mid = l + r >> 1; build (lson); build (rson); } void updata(int ql, int qr, int l, int r, int o) { if (ql <= l && r <= qr) { flip (l, r, o); return ; } if (l == r) return ; //! push_down (l, r, o); int mid = l + r >> 1; if (ql <= mid) updata (ql, qr, lson); if (qr > mid) updata (ql, qr, rson); push_up (o); } int query(int ql, int qr, int l, int r, int o) { if (ql <= l && r <= qr) { return s[o]; } push_down (l, r, o); int mid = l + r >> 1, ret = 0; if (ql <= mid) ret += query (ql, qr, lson); if (qr > mid) ret += query (ql, qr, rson); push_up (o); return ret; }}W, L;std::vector
edge[N];int sz[N], dep[N], son[N], fa[N];int pos[N], belong[N];int loc;int n;int query(int u, int v) { int p = belong[u], q = belong[v], ret = 0; while (p != q) { if (dep[p] < dep[q]) { std::swap (p, q); std::swap (u, v); } if (u != p) { ret += W.query (pos[son[p]], pos[u], 1, n, 1); } ret += (W.query (pos[p], pos[p], 1, n, 1) ^ L.query (pos[fa[p]], pos[fa[p]], 1, n, 1)); u = fa[p]; p = belong[u]; } if (u == v) return ret; if (dep[u] < dep[v]) { std::swap (u, v); } ret += W.query (pos[son[v]], pos[u], 1, n, 1); return ret;}void modify(int t, int u, int v) { int p = belong[u], q = belong[v]; while (p != q) { if (dep[p] < dep[q]) { std::swap (p, q); std::swap (u, v); } if (t == 1) { W.updata (pos[p], pos[u], 1, n, 1); } else { L.updata (pos[p], pos[u], 1, n, 1); W.updata (pos[son[u]], pos[son[u]], 1, n, 1); W.updata (pos[p], pos[p], 1, n, 1); } u = fa[p]; p = belong[u]; } if (dep[u] < dep[v]) { std::swap (u, v); } if (t == 1) { if (u == v) return ; W.updata (pos[son[v]], pos[u], 1, n, 1); } else { L.updata (pos[v], pos[u], 1, n, 1); W.updata (pos[son[u]], pos[son[u]], 1, n, 1); W.updata (pos[v], pos[v], 1, n, 1); }}//树链剖分void DFS2(int u, int chain) { pos[u] = ++loc; belong[u] = chain; if (son[u]) { DFS2 (son[u], chain); } for (auto v: edge[u]) { if (v == fa[u] || v == son[u]) continue; DFS2 (v, v); }}void DFS1(int u, int pa) { sz[u] = 1; dep[u] = dep[pa] + 1; son[u] = 0; fa[u] = pa; for (auto v: edge[u]) { if (v == pa) continue; DFS1 (v, u); sz[u] += sz[v]; if (sz[son[u]] < sz[v]) son[u] = v; }}void prepare() { sz[0] = dep[0] = fa[0] = 0; DFS1 (1, 0); loc = 0; DFS2 (1, 1); W.build (1, n, 1); L.build (1, n, 1);}void init_edge(int n) { for (int i=1; i<=n; ++i) { edge[i].clear (); }}int main() { int T; scanf ("%d", &T); while (T--) { scanf ("%d", &n); init_edge (n); for (int i=1; i

  

 

转载于:https://www.cnblogs.com/Running-Time/p/5669064.html

你可能感兴趣的文章
[SCOI2005][BZOJ 1084]最大子矩阵
查看>>
学习笔记之Data Visualization
查看>>
Leetcode 3. Longest Substring Without Repeating Characters
查看>>
【FJOI2015】金币换位问题
查看>>
数学之美系列二十 -- 自然语言处理的教父 马库斯
查看>>
Android实现自定义位置无标题Dialog
查看>>
面试总结
查看>>
Chrome浏览器播放HTML5音频没声音的解决方案
查看>>
easyui datagrid 行编辑功能
查看>>
HDU 2818 (矢量并查集)
查看>>
实验二 Java面向对象程序设计
查看>>
------__________________________9余数定理-__________ 1163______________
查看>>
webapp返回上一页 处理
查看>>
新安装的WAMP中phpmyadmin的密码问题
查看>>
20172303 2017-2018-2 《程序设计与数据结构》第5周学习总结
查看>>
eclipse中将一个项目作为library导入另一个项目中
查看>>
Go语言学习(五)----- 数组
查看>>
Android源码学习之观察者模式应用
查看>>
416. Partition Equal Subset Sum
查看>>
Django之FBV与CBV
查看>>