题目链接:  http://acm.hdu.edu.cn/showproblem.php?pid=4897

题意:

给你一棵树,一开始每条边都是白色,有三种操作:

1.将 u - v路径上的边转换颜色

2.将 u - v路径上相邻的边转换颜色

3.求 u - v 路径上黑色边的数量

思路:

好变态的一道树链剖分啊。。。。写自闭了

首先树链剖分,用点表示边.然后就是非常绕的轻重链的维护了,我们用两棵线段树来进行维护,一颗维护重链上的,一棵维护轻链上的标记值。

第一种操作,重链的话直接线段树区间操作i,轻链的话由于第二个操作,它的颜色会被两个点影响(本身和父节点),两个端点颜色不相同时,它才会改变颜色,这里因为他是第一个操作我们直接对它的值进行修改,用另一棵线段树来维护第二个操作对点的标记,对于轻链异或两个端点的标记值再异或第一个操作得到的值就是需要的值。

第二种操作,我们要多建一颗线段树来维护哪点被标记了,需要考虑会有重链上的点与路径相交,上面说了我们重链上的点是用第一颗线段树直接求值的,这种情况下重链是会到影响的,所以我们需要在线段树上更新被影响的点,那么是哪些点会被影响,当轻链向上跳的时候时会有重链在它旁边,这些重边就是被影响的。

第三个操作:重链上的直接用第一颗线段树求,轻链上的点的值就一个一个根据第二棵线段树异或得到。

这道题代码量比较大,写起来要理清思路,要不越写越乱。。。

实现代码:

#include<bits/stdc++.h>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define mid int m = (l + r) >> 1
const int M = 5e5+; int sum[M],lazy[M],lazyl[M],head[M],son[M],siz[M];
int dep[M],fa[M],tid[M],top[M],col[M],Xor[M];
int cnt,cnt1,n;
struct node{
int to,next;
}e[M]; void add(int u,int v){
e[++cnt].to = v;e[cnt].next = head[u];head[u] = cnt;
} void dfs(int u,int faz,int deep){
dep[u] = deep;
siz[u] = ;
fa[u] = faz;
for(int i = head[u];i;i=e[i].next){
int v = e[i].to;
if(v == faz) continue;
dfs(v,u,deep+);
siz[u] += siz[v];
if(son[u] == -||siz[v] > siz[son[u]])
son[u] = v;
}
} void dfs1(int u,int t){
top[u] = t;
tid[u] = ++cnt1;
if(son[u] == -) return ;
dfs1(son[u],t);
for(int i = head[u];i;i=e[i].next){
int v = e[i].to;
if(v != son[u]&&v != fa[u])
dfs1(v,v);
}
} void init(){
cnt1 = ; cnt = ;
memset(son,-,sizeof(son));
memset(head,,sizeof(head));
memset(sum,,sizeof(sum));
memset(fa,,sizeof(fa));
memset(col,,sizeof(col));
memset(lazy,,sizeof(lazy));
memset(lazyl,,sizeof(lazyl));
memset(Xor,,sizeof(Xor));
memset(dep,,sizeof(dep));
memset(top,,sizeof(top));
memset(tid,,sizeof(tid));
} void pushup(int rt){
sum[rt] = sum[rt<<] + sum[rt<<|];
} void pushdown(int l,int r,int rt){
if(lazy[rt]){
mid;
if(l != ) sum[rt<<] = m-l+-sum[rt<<];
else sum[rt<<] = m-l-sum[rt<<];
sum[rt<<|] = r-m-sum[rt<<|];
lazy[rt<<] ^= ; lazy[rt<<|] ^= ;
lazy[rt] = ;
}
} void updatew(int L,int R,int l,int r,int rt){
if(L <= l&&R >= r){
lazy[rt] ^= ;
if(l != ) sum[rt] = r-l+-sum[rt];
else sum[rt] = r-l+sum[rt];
return ;
}
pushdown(l,r,rt);
mid;
if(L <= m) updatew(L,R,lson);
if(R > m) updatew(L,R,rson);
pushup(rt);
} int queryw(int L,int R,int l,int r,int rt){
if(L <= l&&R >= r){
return sum[rt];
}
pushdown(l,r,rt);
int ret = ;
mid;
if(L <= m) ret += queryw(L,R,lson);
if(R > m) ret += queryw(L,R,rson);
return ret;
} void pushdownl(int rt){
if(lazyl[rt]){
lazyl[rt<<] ^= ;
lazyl[rt<<|] ^= ;
lazyl[rt] = ;
}
}
void updatel(int L,int R,int l,int r,int rt){
if(L <= l&&R >= r){
lazyl[rt] ^= ;
return ;
}
mid;
if(L <= m) updatel(L,R,lson);
if(R > m) updatel(L,R,rson);
} int queryl(int p,int l,int r,int rt){
if(l == r) {
return Xor[rt]^lazyl[rt];
}
pushdownl(rt);
mid;
if(p <= m) return queryl(p,lson);
else return queryl(p,rson);
} int addl(int x,int y){
int fx = top[x],fy = top[y];
while(fx != fy){
if(dep[fx] < dep[fy]) swap(fx,fy),swap(x,y);
if(son[x]!=-) updatew(tid[son[x]],tid[son[x]],,n,);
updatel(tid[fx],tid[x],,n,);
x = fa[fx]; fx = top[x];
}
if(dep[x] > dep[y]) swap(x,y);
if(son[x] != -&&x == y) updatew(tid[son[x]],tid[son[x]],,n,);
if(x != y&&son[y] != -) updatew(tid[son[y]],tid[son[y]],,n,);
if(x != &&son[fa[x]] == x) updatew(tid[x],tid[x],,n,);
updatel(tid[x],tid[y],,n,);
} void addw(int x,int y){
int fx = top[x],fy = top[y];
while(fx != fy){
if(dep[fx] < dep[fy]) swap(fx,fy),swap(x,y);
if(fx != x) updatew(tid[son[fx]],tid[x],,n,);
col[fx] ^= ; x = fa[fx]; fx = top[x];
}
if(x != y){
if(dep[x] < dep[y]&&son[x] != -) updatew(tid[son[x]],tid[y],,n,);
else if(son[y] != -) updatew(tid[son[y]],tid[x],,n,);
}
} int solve(int x,int y){
int ret = ;
int fx = top[x],fy = top[y];
while(fx != fy){
if(dep[fx] < dep[fy]) swap(x,y),swap(fx,fy);
if(fx != x) ret += queryw(tid[son[fx]],tid[x],,n,);
int num = queryl(tid[fx],,n,)^queryl(tid[fa[fx]],,n,);
ret += num^col[fx];
x = fa[fx]; fx = top[x];
}
if(x != y){
if(dep[x] < dep[y]&&son[x] != -) ret += queryw(tid[son[x]],tid[y],,n,);
else if(son[y] != -) ret += queryw(tid[son[y]],tid[x],,n,);
}
return ret;
} int main()
{
int t,u,v,op,x,y,q;
scanf("%d",&t);
while(t--){
init();
scanf("%d",&n);
for(int i = ;i < n;i ++){
int x,y;
scanf("%d%d",&u,&v);
add(u,v); add(v,u);
}
dfs(,,);
dfs1(,);
scanf("%d",&q);
while(q--){
scanf("%d%d%d",&op,&x,&y);
if(op == ){
addw(x,y);
}
else if(op == ){
addl(x,y);
}
else{
if(x == y) printf("0\n");
else
printf("%d\n",solve(x,y));
}
}
}
return ;
}

hdu 4897 Little Devil I (树链剖分+线段树)的更多相关文章

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

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

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

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

  3. HDU4897 (树链剖分+线段树)

    Problem Little Devil I (HDU4897) 题目大意 给定一棵树,每条边的颜色为黑或白,起始时均为白. 支持3种操作: 操作1:将a->b的路径中的所有边的颜色翻转. 操作 ...

  4. Aragorn's Story 树链剖分+线段树 && 树链剖分+树状数组

    Aragorn's Story 来源:http://www.fjutacm.com/Problem.jsp?pid=2710来源:http://acm.hdu.edu.cn/showproblem.p ...

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

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

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

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

  7. BZOJ2243 (树链剖分+线段树)

    Problem 染色(BZOJ2243) 题目大意 给定一颗树,每个节点上有一种颜色. 要求支持两种操作: 操作1:将a->b上所有点染成一种颜色. 操作2:询问a->b上的颜色段数量. ...

  8. POJ3237 (树链剖分+线段树)

    Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...

  9. bzoj4034 (树链剖分+线段树)

    Problem T2 (bzoj4034 HAOI2015) 题目大意 给定一颗树,1为根节点,要求支持三种操作. 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子 ...

  10. 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 ...

随机推荐

  1. Android Studio复制项目作为一个新的工程

    Android Studio复制项目作为一个新的工程 等待..... 好了 可能会安装失败 Failed to finalize session : INSTALL_FAILED_INVALID_AP ...

  2. day90

    Vue项目简介 最终效果:Vue通过axios发请求给Django后台,Django返回数据给Vue 创建项目: 创建vue项目: -安装node.js -vue脚手架 -vue create 项目名 ...

  3. 7、存储类 & 作用域 & 生命周期 & 链接属性

    概念解析 存储类 存储类就是存储类型,也就是描述C语言变量在何种地方存储. 内存有多种管理方法:栈.堆.数据段.bss段..text段······一个变量的存储类属性就是描述这个变量存储在何种内存段中 ...

  4. Luogu P4211 [LNOI2014]LCA

    我去这道题的Luogu评级是假的吧,这都算黑题. 我们首先考虑把操作离线不强制在线的题目离线一下一般都要方便些 考虑差分,我们用\(f(x)\)表示\([1,x]\)之间的点与\(z\)的答案,那么显 ...

  5. c++对象模型-对象模型

    1:简单对象模型 1>介绍:每个成员都使用一个指针指向真正的成员.所以对象 的大小很好确定,就是成员数*指针大小. 2>用途:成员函数就是使用这个模型的 3>图: 4>加上继承 ...

  6. 20135337——Linux实践二:模块

    一.编译&生成&测试&删除 1.编写模块代码,查看如下 gedit 1.c(编写) cat 1.c(查看) MODULE_AUTHOR("Z") MODUL ...

  7. 网络:OSPF理解

    OSPF(开放最短路径优先)协议使用Dijkstra算法,常见的版本有:OSPFv2.OSPFv3等.以下主要介绍OSPFv2,OSPFv3是面向IPv6的且不兼容IPv4. 1.工作过程: 1)每台 ...

  8. git工具

    1.Git Bash常用命令: pwd    当前工作目录 clear   清屏 ls   列举当前目录下的文件及文件夹 cd 更改目录 mkdir   创建目录 touch   创建空文件 cp 拷 ...

  9. 第三个Sprint冲刺第五天(燃尽图)

  10. 总结 推广app

    扫一扫二维码即可安装使用我们的app,方便快捷. 电脑端下载地址:http://pan.baidu.com/s/1bocWPPX http://a.app.qq.com/o/simple.jsp?pk ...