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

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

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

题意:

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

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

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

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

思路:

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

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

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

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

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

 

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

实现代码:

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

 

转载于:https://www.cnblogs.com/kls123/p/9643771.html

你可能感兴趣的文章
python之-框架
查看>>
Gradle多项目构建
查看>>
Java基础教程——网络基础知识
查看>>
c++文件的读写
查看>>
[Web] 如何实现Web服务器和应用服务器的负载均衡?
查看>>
创建文件夹命令
查看>>
自己到底要的是什么
查看>>
this 指向
查看>>
Kruskal基础最小生成树
查看>>
【RabbitMQ】 Java简单的实现RabbitMQ
查看>>
BZOJ.4819.[SDOI2017]新生舞会(01分数规划 费用流SPFA)
查看>>
ubuntu 14.04 安装搜狗拼音输入法
查看>>
c#中 uint--byte[]--char[]--string相互转换汇总
查看>>
- C#编程大幅提高OUTLOOK的邮件搜索能力!
查看>>
InstallShield Limited Edition for Visual Studio 2013 图文教程(教你如何打包.NET程序)
查看>>
Windows 8.1 应用再出发 - 几种布局控件
查看>>
浅谈算法和数据结构: 一 栈和队列
查看>>
[WebMatrix] 如何将SQL Compact 4.0 移转至SQL Server 2008 Express
查看>>
Java内部类详解
查看>>
验证码类[置顶] SSO单点登录系列5:cas单点登录增加验证码功能完整步骤
查看>>