hdu 4897 Little Devil I (树链剖分+线段树)
题目链接: 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 (树链剖分+线段树)的更多相关文章
- HDU 2460 Network(双连通+树链剖分+线段树)
HDU 2460 Network 题目链接 题意:给定一个无向图,问每次增加一条边,问个图中还剩多少桥 思路:先双连通缩点,然后形成一棵树,每次增加一条边,相当于询问这两点路径上有多少条边,这个用树链 ...
- BZOJ3862Little Devil I——树链剖分+线段树
题目大意: 给一棵树,每条边可能是黑色或白色(起始都是白色),有三种操作: 1.将u到v路径上所有边颜色翻转(黑->白,白->黑) 2.将只有一个点在u到v路径上的边颜色翻转 3.查询u到 ...
- HDU4897 (树链剖分+线段树)
Problem Little Devil I (HDU4897) 题目大意 给定一棵树,每条边的颜色为黑或白,起始时均为白. 支持3种操作: 操作1:将a->b的路径中的所有边的颜色翻转. 操作 ...
- Aragorn's Story 树链剖分+线段树 && 树链剖分+树状数组
Aragorn's Story 来源:http://www.fjutacm.com/Problem.jsp?pid=2710来源:http://acm.hdu.edu.cn/showproblem.p ...
- 【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 为根的子 ...
- 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 ...
随机推荐
- 一次学生时代的经历,利用Python在机房杀红蜘蛛,脱离老师控制!
这个为什么说是一次学生时代的经历呢,我的出发点并没有是为了吊胃口.确实,这个Python小应用,只能在学生时代用得着吧,尤其是高中和大学,如果你没有想到也没关系,看完我下面说的就会明白了. 在这里 ...
- CentOS7.2调整Mysql数据库最大连接数
mysql数据库最大连接数=max_connections+11:root连接,用于管理员连接数据库进行维护操作查看最大连接数:show variables like 'max_connections ...
- Python学习总结 05 pandas
pandas官方网址 : http://pandas.pydata.org/ . pandas的安装比较复杂,如果想开箱即用,可以考虑下载WinPython.WinPython的官方地址是: htt ...
- LOJ540 游戏 构造
传送门 题意:给出$N$,试构造一个点数小于$500$的图,使得其中三元环的个数恰好为$N$.$N \leq 2 \times 10^6$ 首先构造一个尽可能大的完全图,然后在这个完全图旁边加点.尽可 ...
- 在线图标制作,格式转换 ICON
在线图标制作,格式转换 https://www.easyicon.net/covert/
- Create-React-App 使用记录
如果要修改 host 和 端口,需要在项目根目录添加 .env 文件,然后再文件中添加 HOST=dev.zhengtongauto.com PORT=3000 如果需要加上反向代理,需要处理接口跨域 ...
- windows服务中对外提供API接口
public class SendMqService { private static bool isExcute = true; private static HttpListener listen ...
- Python进阶量化交易专栏场外篇7- 装饰器计算代码时间
欢迎大家订阅<教你用 Python 进阶量化交易>专栏!为了能够提供给大家更轻松的学习过程,笔者在专栏内容之外已陆续推出一些手记来辅助同学们学习本专栏内容,目前已推出如下扩展篇: 在第一篇 ...
- 个人阅读作业2—《No Silver Bullet: Essence and Accidents of Software Engineering》读后感
在进行了一次结对编程.一次团队编程和一次个人编程项目后,读了<No Silver Bullet: Essence and Accidents of Software Engineering> ...
- M2 终审
1.团队成员简介 左边:马腾跃 右边:陈谋 左上:李剑锋 左下:仉伯龙 右:卢惠明 团队成员及博客: 李剑锋: Blog: http://www.cnblogs.com/Po ...