树链剖分+线段树 HDOJ 4897 Little Devil I(小恶魔)
题意:
给定一棵树,每条边有黑白两种颜色,初始都是白色,现在有三种操作:
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;
}
树链剖分+线段树 HDOJ 4897 Little Devil I(小恶魔)的更多相关文章
- 【BZOJ-2325】道馆之战 树链剖分 + 线段树
2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 1153 Solved: 421[Submit][Statu ...
- 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树
[BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...
- BZOJ2243 (树链剖分+线段树)
Problem 染色(BZOJ2243) 题目大意 给定一颗树,每个节点上有一种颜色. 要求支持两种操作: 操作1:将a->b上所有点染成一种颜色. 操作2:询问a->b上的颜色段数量. ...
- POJ3237 (树链剖分+线段树)
Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...
- bzoj4034 (树链剖分+线段树)
Problem T2 (bzoj4034 HAOI2015) 题目大意 给定一颗树,1为根节点,要求支持三种操作. 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子 ...
- HDU4897 (树链剖分+线段树)
Problem Little Devil I (HDU4897) 题目大意 给定一棵树,每条边的颜色为黑或白,起始时均为白. 支持3种操作: 操作1:将a->b的路径中的所有边的颜色翻转. 操作 ...
- Aizu 2450 Do use segment tree 树链剖分+线段树
Do use segment tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.bnuoj.com/v3/problem_show ...
- 【POJ3237】Tree(树链剖分+线段树)
Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edg ...
- HDU 2460 Network(双连通+树链剖分+线段树)
HDU 2460 Network 题目链接 题意:给定一个无向图,问每次增加一条边,问个图中还剩多少桥 思路:先双连通缩点,然后形成一棵树,每次增加一条边,相当于询问这两点路径上有多少条边,这个用树链 ...
- bzoj2243[SDOI2011]染色 树链剖分+线段树
2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 9012 Solved: 3375[Submit][Status ...
随机推荐
- windows安装rabbitmq
官网下载windows安装版本:http://www.rabbitmq.com/install-windows.html ,安装文件rabbitmq-server-3.6.5.exe 前提:安装erl ...
- ueditor 1.4.3 gbk asp 上传中文乱码 终极解决方法 ie6 ie8 也适用
[摘要:百度编纂器1.43 gbk asp 题目 1.firefox3.0下 单图上传 面没有了 面多图上传 中央的蓝色按钮(即 面击挑选图片)没有表现(附件上传出那个题目) 没有晓得我的水狐吃翔了 ...
- 多个.ui共用一个.qrc出错
在一个已经组建完成的qt项目中,如果再加入新的界面文件,界面文件是无法直接使用原工程的.qrc文件的(执行添加资源操作时不显示资源文件),必须重启一次Qt. 版本: Qt 5.7.0 Qt Creat ...
- mysql中的行转列
//查看当前商品库存 function checkProductStock($product_id){ global $wpdb; $sql="SELECT post_id,max(if(( ...
- Angular2 组件通信
1. 组件通信 我们知道Angular2应用程序实际上是有很多父子组价组成的组件树,因此,了解组件之间如何通信,特别是父子组件之间,对编写Angular2应用程序具有十分重要的意义,通常来讲,组件之间 ...
- IntelliJ IDEA WEB项目的部署配置
以下内容是我网上找的比较全面了,其中关于facets配置很多地方都没有说明,其实很重要,我加入了自己的理解.其他来自网络.在导入一个项目有问题时,建议先创建一个正确的web项目,然后对比配置项,一般就 ...
- 在input中放对象
var input = $("<input type='hidden' class='hidden-user'/>"); $(input).data("ran ...
- GitHub Desktop+码云(GIT.oschina)使用方法
一.如何从码云GIT导入到GitHubDeskTop桌面工具. 1.先用命令行切换到本地的目录. 2.使用git clone 码云GIT地址 命令将项目克隆到本地. 3.在GitHub Desktop ...
- 解决UC浏览器或微信浏览器上flex兼容问题
在UC浏览器上使用display:flex;时会不起作用,要加上兼容性写法,如下 display: -webkit-box; /* OLD - iOS 6-, Safari 3.1-6 */ disp ...
- 利用html5、websocket和opencv实现人脸检测 (二)
前一篇的代码在执行时,java.exe占用内存会快速上涨: 在4G内存电脑上,单个连接,会持续上涨到2G多,然后减到1G多,如此循环. 经过一些删减定位,可以确定问题由public byte[] pr ...