题目链接

题意:

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

    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 <bits/stdc++.h>const int N = 1e5 + 5;//线段树
#define lson l, mid, o << 1
#define rson mid + 1, r, o << 1 | 1
struct 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<int> 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<n; ++i) {int u, v;scanf ("%d%d", &u, &v);edge[u].push_back (v);edge[v].push_back (u);}prepare ();int q;scanf ("%d", &q);while (q--) {int t, u, v;scanf ("%d%d%d", &t, &u, &v);if (t == 3) {printf ("%d\n", query (u, v));} else {modify (t, u, v);}}}return 0;
}

  

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

树链剖分+线段树 HDOJ 4897 Little Devil I(小恶魔)相关推荐

  1. 【BZOJ-2325】道馆之战 树链剖分 + 线段树

    2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec  Memory Limit: 256 MB Submit: 1153  Solved: 421 [Submit][Sta ...

  2. BZOJ3862Little Devil I——树链剖分+线段树

    题目大意: 给一棵树,每条边可能是黑色或白色(起始都是白色),有三种操作: 1.将u到v路径上所有边颜色翻转(黑->白,白->黑) 2.将只有一个点在u到v路径上的边颜色翻转 3.查询u到 ...

  3. CodeForces - 160D Edges in MST(思维+tarjan/树链剖分+线段树)

    题目链接:点击查看 题目大意:给出一张 n 个点 m 条边组成的带权无向图,现在对于每条边来说,确定一下其分类: 一定是最小生成树上的边 可能是最小生成树上的边 一定不是最小生成树的边 题目分析:两种 ...

  4. CodeForces - 609E Minimum spanning tree for each edge(最小生成树+树链剖分+线段树/树上倍增)

    题目链接:点击查看 题目大意:给出一张 n 个点和 m 条边组成的无向图,现在询问包含每一条边的最小生成树 题目分析:考虑求解次小生成树的思路: 求出最小生成树 ans 枚举每一条非树边 ( u , ...

  5. P2486 [SDOI2011]染色(树链剖分+线段树)

    题干描述 输入描述 输出格式 对于每个询问操作,输出一行答案. 输入输出样例 输入 #1 复制 6 5 2 2 1 2 1 1 1 2 1 3 2 4 2 5 2 6 Q 3 5 C 2 1 1 Q ...

  6. BZOJ4127Abs——树链剖分+线段树

    题目描述 给定一棵树,设计数据结构支持以下操作 1 u v d 表示将路径 (u,v) 加d 2 u v 表示询问路径 (u,v) 上点权绝对值的和 输入 第一行两个整数n和m,表示结点个数和操作数 ...

  7. 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树

    [BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...

  8. HDU 2460 Network(双连通+树链剖分+线段树)

    HDU 2460 Network 题目链接 题意:给定一个无向图,问每次增加一条边,问个图中还剩多少桥 思路:先双连通缩点,然后形成一棵树,每次增加一条边,相当于询问这两点路径上有多少条边,这个用树链 ...

  9. BZOJ2325[ZJOI2011]道馆之战——树链剖分+线段树

    题目描述 口袋妖怪(又名神奇宝贝或宠物小精灵)红/蓝/绿宝石中的水系道馆需要经过三个冰地才能到达馆主的面前,冰地中 的每一个冰块都只能经过一次.当一个冰地上的所有冰块都被经过之后,到下一个冰地的楼梯才 ...

  10. YbtOJ-染色计划【树链剖分,线段树,tarjan】

    正题 题目大意 给出nnn个点的一棵树,每个点有个颜色aia_iai​,你每次可以选择一个颜色全部变成另一个颜色. 求最少多少次操作可以把一种颜色变成一个完整的连通块. 1≤k≤n≤2×1051\le ...

最新文章

  1. 浅析枚举类型(Enumerated types)
  2. JS的对象及其属性和方法
  3. 遍历Map key-value的两种方法、遍历Set方法
  4. Java forEach() 方法的三种用法
  5. quartus仿真18:仿真简单D触发器和JK触发器输出的波形
  6. Linux进程状态(ps stat)之R、S、D、T、Z、X 转:http://blog.csdn.net/huzia/article/details/18946491...
  7. linux shell awk -F‘:‘ ‘{print $1}‘
  8. 23种设计模式总结+清晰图解(必收藏)
  9. sqlserver 执行计划
  10. 苹果6s强制删除id锁_苹果ID锁安全神话破灭!2分钟就能解锁
  11. java170道面试题汇总+详细解析
  12. java rd th 小票机_英语日期rd,th有什么区别,怎么运用
  13. React中文文档之Conditional Rendering
  14. 亚特兰提斯之人鱼宝宝
  15. Unirech:为什么不能访问阿里云国际版云服务器ecs实例上的网站
  16. 数据集-20个免费的数据源/网站
  17. matlab中将数据保存为txt文件_matlab中将数据输出保存为txt格式文件的方式
  18. 简易防火墙建置与流量统计
  19. $我不是韭菜--基金篇(力哥P1-P6)$
  20. 卡拉兹猜想证明用python_科普:数学领域中的感觉像是“民科”的卡拉兹猜想

热门文章

  1. 伍六七带你学算法 入门篇-最长回文串
  2. 2022-2028年中国激光玻璃行业市场供需规模及发展趋势研究报告
  3. 消除安卓SDK更新时的“https://dl-ssl.google.com refused”异常的方法
  4. LeetCode简单题之差的绝对值为 K 的数对数目
  5. LeetCode简单题之递增顺序搜索树
  6. LeetCode简单题之棒球比赛
  7. 左神讲算法——二分法及其拓展
  8. CPU Cache原理与示例
  9. TVM性能评估分析(五)
  10. 空间点像素索引(一)