题目大意:

给一棵树,每条边可能是黑色或白色(起始都是白色),有三种操作:

1、将u到v路径上所有边颜色翻转(黑->白,白->黑)

2、将只有一个点在u到v路径上的边颜色翻转

3、查询u到v路径上颜色为黑色的边数

如果只有1、3操作很好做,直接树链剖分+线段树,重点是2操作(废话)。

可以发现只有lca需要翻转和它父节点之间的边,因此将这条边暴力翻转。

现在剩下需要翻转的就是u到v路径上所有点与他们子节点之间的边。

我们将u到v的路径分成若干条重链,可以发现每条重链除了链低端的那个点,其他点要反转的是他们与他们所有轻儿子之间的边(这里注意特判lca少翻转了一条轻边)。

这么多边显然不能都翻转,那么我们再开一棵线段树,将重链上的点打标记,代表这些点与他们所有轻儿子之间的边需要翻转。

至于重链低端那个点还要暴力翻转它与重儿子间的边。

但现在只处理了每条重链,没有考虑两条链之间连接的那条边?

假设y链接在x链下面,那么x链低端那个点需要翻转的是除了一个轻边之外的其他轻边和一条重边,那么只需要将重边和不需要翻转的轻边翻转之后再打标记就好了。

将边下传到点,开两棵线段树,一棵维护边的颜色,另一棵维护给轻儿子翻转的标记(这棵线段树建议标记永久化),每次修改时注意链与链之间轻边的翻转即可。

#include<set>
#include<map>
#include<stack>
#include<queue>
#include<cmath>
#include<cstdio>
#include<vector>
#include<bitset>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
int T;
int n,m;
int x,y;
int tot;
int opt;
int num;
int a[800010];
int b[800010];
int d[100010];
int f[100010];
int s[100010];
int to[200010];
int sum[800010];
int son[100010];
int top[100010];
int size[100010];
int head[100010];
int next[200010];
void add(int x,int y)
{tot++;next[tot]=head[x];head[x]=tot;to[tot]=y;
}
void dfs(int x)
{d[x]=d[f[x]]+1;size[x]=1;for(int i=head[x];i;i=next[i]){if(to[i]!=f[x]){f[to[i]]=x;dfs(to[i]);size[x]+=size[to[i]];if(size[to[i]]>size[son[x]]){son[x]=to[i];}}}
}
void dfs2(int x,int tp)
{s[x]=++num;top[x]=tp;if(son[x]){dfs2(son[x],tp);}for(int i=head[x];i;i=next[i]){if(to[i]!=f[x]&&to[i]!=son[x]){dfs2(to[i],to[i]);}}
}
void updata(int rt,int l,int r,int L,int R)
{if(L<=l&&r<=R){b[rt]^=1;return ;}int mid=(l+r)>>1;if(L<=mid){updata(rt<<1,l,mid,L,R);}if(R>mid){updata(rt<<1|1,mid+1,r,L,R);}
}
int downdata(int rt,int l,int r,int k)
{if(l==r){return b[rt];}int res=b[rt];int mid=(l+r)>>1;if(k<=mid){return res^downdata(rt<<1,l,mid,k);}else{return res^downdata(rt<<1|1,mid+1,r,k);}
}
void pushup(int rt)
{sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void pushdown(int rt,int l,int r)
{if(a[rt]){int mid=(l+r)>>1;a[rt<<1]^=1;a[rt<<1|1]^=1;sum[rt<<1]=(mid-l+1)-sum[rt<<1];sum[rt<<1|1]=(r-mid)-sum[rt<<1|1];a[rt]=0;}
}
void change1(int rt,int l,int r,int k)
{if(l==r){sum[rt]^=1;return ;}pushdown(rt,l,r);int mid=(l+r)>>1;if(k<=mid){change1(rt<<1,l,mid,k);}else{change1(rt<<1|1,mid+1,r,k);}pushup(rt);
}
void change2(int rt,int l,int r,int L,int R)
{if(L<=l&&r<=R){a[rt]^=1;sum[rt]=(r-l+1)-sum[rt];return ;}pushdown(rt,l,r);int mid=(l+r)>>1;if(L<=mid){change2(rt<<1,l,mid,L,R);}if(R>mid){change2(rt<<1|1,mid+1,r,L,R);}pushup(rt);
}
int query1(int rt,int l,int r,int k)
{if(l==r){return sum[rt];}pushdown(rt,l,r);int mid=(l+r)>>1;if(k<=mid){return query1(rt<<1,l,mid,k);}else{return query1(rt<<1|1,mid+1,r,k);}
}
int query2(int rt,int l,int r,int L,int R)
{if(L<=l&&r<=R){return sum[rt];}pushdown(rt,l,r);int mid=(l+r)>>1;int res=0;if(L<=mid){res+=query2(rt<<1,l,mid,L,R);}if(R>mid){res+=query2(rt<<1|1,mid+1,r,L,R);}return res;
}
void rotate1(int x,int y)
{while(top[x]!=top[y]){if(d[top[x]]<d[top[y]]){swap(x,y);}change2(1,1,n,s[top[x]],s[x]);x=f[top[x]];}if(d[x]>d[y]){swap(x,y);}if(x==y){return ;}change2(1,1,n,s[x]+1,s[y]);
}
void rotate2(int x,int y)
{if(son[x]){change1(1,1,n,s[x]+1);}if(son[y]){change1(1,1,n,s[y]+1);}while(top[x]!=top[y]){if(d[top[x]]<d[top[y]]){swap(x,y);}updata(1,1,n,s[top[x]],s[x]);change1(1,1,n,s[top[x]]);x=f[top[x]];change1(1,1,n,s[x]+1);}if(d[x]>d[y]){swap(x,y);}change1(1,1,n,s[x]);change1(1,1,n,s[x]+1);updata(1,1,n,s[x],s[y]);
}
int ask(int x,int y)
{int res=0;int ans;while(top[x]!=top[y]){if(d[top[x]]<d[top[y]]){swap(x,y);}if(top[x]!=x){res+=query2(1,1,n,s[top[x]]+1,s[x]);}ans=query1(1,1,n,s[top[x]]);x=f[top[x]];res+=(ans^downdata(1,1,n,s[x]));}if(d[x]>d[y]){swap(x,y);}if(x==y){return res;}res+=query2(1,1,n,s[x]+1,s[y]);return res;
}
int main()
{scanf("%d",&T);while(T--){num=0;tot=0;memset(a,0,sizeof(a));memset(b,0,sizeof(b));memset(f,0,sizeof(f));memset(d,0,sizeof(d));memset(s,0,sizeof(s));memset(to,0,sizeof(to));memset(son,0,sizeof(son));memset(top,0,sizeof(top));memset(sum,0,sizeof(sum));memset(size,0,sizeof(size));memset(head,0,sizeof(head));memset(next,0,sizeof(next));scanf("%d",&n);for(int i=1;i<n;i++){scanf("%d%d",&x,&y);add(x,y);add(y,x);}dfs(1);dfs2(1,1);scanf("%d",&m);for(int i=1;i<=m;i++){scanf("%d%d%d",&opt,&x,&y);if(opt==1){rotate1(x,y);}else if(opt==2){rotate2(x,y);}else{printf("%d\n",ask(x,y));}}}
}

转载于:https://www.cnblogs.com/Khada-Jhin/p/9719205.html

BZOJ3862Little Devil I——树链剖分+线段树相关推荐

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

最新文章

  1. [转载]静态构造函数
  2. 干货!任正非对话美国科技思想家,都说了些什么
  3. 分享10个实用的超绚CSS3按钮设计
  4. 借助开源工具高效完成Java应用的运行分析
  5. H.263 H.263+ Payload Type
  6. Google Jump Consistent Hash 一致性哈希算法
  7. 设计原则 —— 针对接口编程而不针对实现编程
  8. Android Studio稍微较新的版本下载
  9. 软考解析:2017年下半年下午试卷
  10. 帮助干活,朋友馈赠了购物卡
  11. c语言鼠标游戏代码,自己用C写的一个简单的打地鼠游戏代码出了个问题(鼠标和循环不能...
  12. TS2339: Property 'debounceTime' does not exist on type 'Observableany'. - Angular 6
  13. Escape HDU - 3533
  14. 好看的colormap颜色
  15. JS日期、年月日、时分秒
  16. 拼多多进军教育,学习也能「砍一刀」?
  17. 微博营销,究竟该怎么做?(实战系列一:粉丝篇)
  18. python网络爬虫从入门到实践第2版pdf-Python网络爬虫从入门到实践 第2版
  19. 基于Hi3559A ARM64位嵌入式平台的OpenCV2.4.9+ffmpeg2.0.7移植及应用
  20. Symantec赛门铁克支持型SSL服务器证书_网站安全SSL数字证书认证

热门文章

  1. boost::hana::min用法的测试程序
  2. boost::hana::second用法的测试程序
  3. boost::mpl::integral_c用法的测试程序
  4. boost::ReadablePropertyMapConcept用法的测试程序
  5. boost::coroutine模块实现合并数组的测试程序
  6. boost::contract模块实现stack的测试程序
  7. ITK:将蒙版的反面应用于图像
  8. VTK:Utilities之BoundingBoxIntersection
  9. VTK:网格之TableBasedClipDataSetWithPolyData
  10. QT实现太阳系系统八大行星