考虑如下构造:

新建一条边$(0,1)$,并将原树以0为根建树,记$fa_{x}$为$x$的父亲(其中$1\le x\le n$)

维护两棵森林,分别记作$T_{0/1}$,每一条边恰属于一棵,其中$(x,fa_{x})\in T_{0}$当且仅当$x$为白色点

此时,考虑节点$x$的答案(不妨假设$x$为白色点),即是$T_{0}$去掉$x$所在连通块根节点(深度最小的节点)后所在连通块子树大小,正确性显然

对这两棵森林使用LCT维护,考虑修改和查询:

1.修改时,即增加并删除一条边

2.查询时,不妨假设$x$为白色,将$T_{0}$中$x$所在连通块内深度最小的点make_root后,不难发现即求该点右儿子子树范围内的点数,显然容易维护("子树范围"定义以及如何维护见QTREE5

考虑如何快速找到该点,考虑保持树的形态(注意初始状态),即在make_root时不rev,那么find_root的结果即为该最浅的点

这样在加边和删边时并不会产生影响(其实通常的LCT在加边和删边时也并不需要rev),查询时的做法上面已经给出,即find_root一下即可

时间复杂度为$o(n\log n)$,可以通过

  1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 100005
4 vector<int>v[N];
5 int n,m,x,y,f[N],col[N];
6 struct LCT{
7 int fa[N],vir[N],sz[N],ch[N][2];
8 LCT(){
9 for(int i=1;i<N;i++)sz[i]=1;
10 }
11 bool check(int k){
12 return ((ch[fa[k]][0]!=k)&&(ch[fa[k]][1]!=k));
13 }
14 int which(int k){
15 return ch[fa[k]][1]==k;
16 }
17 void up(int k){
18 sz[k]=sz[ch[k][0]]+sz[ch[k][1]]+vir[k]+1;
19 }
20 void add_vir(int k){
21 vir[fa[k]]+=sz[k];
22 }
23 void del_vir(int k){
24 vir[fa[k]]-=sz[k];
25 }
26 void rotate(int k){
27 int f=fa[k],g=fa[f],p=which(k);
28 fa[k]=g;
29 if (!check(f))ch[g][which(f)]=k;
30 fa[ch[k][p^1]]=f,ch[f][p]=ch[k][p^1];
31 fa[f]=k,ch[k][p^1]=f;
32 up(f),up(k);
33 }
34 void splay(int k){
35 for(int i=fa[k];!check(k);i=fa[k]){
36 if (!check(i)){
37 if (which(i)==which(k))rotate(i);
38 else rotate(k);
39 }
40 rotate(k);
41 }
42 }
43 void access(int k){
44 int lst=0;
45 while (k){
46 splay(k);
47 if (ch[k][1])add_vir(ch[k][1]);
48 if (lst)del_vir(lst);
49 ch[k][1]=lst,up(k);
50 lst=k,k=fa[k];
51 }
52 }
53 void make_root(int k){
54 access(k);
55 splay(k);
56 }
57 int find_root(int k){
58 access(k);
59 splay(k);
60 while (ch[k][0])k=ch[k][0];
61 splay(k);
62 return k;
63 }
64 void add(int x,int y){
65 make_root(x);
66 make_root(y);
67 fa[y]=x,add_vir(y),up(x);
68 }
69 void del(int x,int y){
70 make_root(x);
71 access(y);
72 fa[y]=ch[x][1]=0,up(x);
73 }
74 int query(int k){
75 k=find_root(k);
76 return sz[ch[k][1]];
77 }
78 }T[2];
79 void dfs(int k,int fa){
80 f[k]=fa;
81 for(int i=0;i<v[k].size();i++)
82 if (v[k][i]!=fa)dfs(v[k][i],k);
83 }
84 int main(){
85 scanf("%d",&n);
86 for(int i=1;i<n;i++){
87 scanf("%d%d",&x,&y);
88 v[x].push_back(y);
89 v[y].push_back(x);
90 }
91 dfs(1,n+1);
92 for(int i=1;i<=n;i++){
93 col[i]=1;
94 T[1].add(f[i],i);
95 }
96 scanf("%d",&m);
97 for(int i=1;i<=m;i++){
98 scanf("%d%d",&x,&y);
99 if (!x)printf("%d\n",T[col[y]].query(y));
100 else{
101 T[col[y]].del(f[y],y);
102 col[y]^=1;
103 T[col[y]].add(f[y],y);
104 }
105 }
106 return 0;
107 }

[spojQTREE6]Query on a tree VI的更多相关文章

  1. bzoj 3637: Query on a tree VI 树链剖分 && AC600

    3637: Query on a tree VI Time Limit: 8 Sec  Memory Limit: 1024 MBSubmit: 206  Solved: 38[Submit][Sta ...

  2. QTREE6 - Query on a tree VI 解题报告

    QTREE6 - Query on a tree VI 题目描述 给你一棵\(n\)个点的树,编号\(1\)~\(n\).每个点可以是黑色,可以是白色.初始时所有点都是黑色.下面有两种操作请你操作给我 ...

  3. bzoj3637: Query on a tree VI

    Description You are given a tree (an acyclic undirected connected graph) with n nodes. The tree node ...

  4. BZOJ3637 Query on a tree VI(树链剖分+线段树)

    考虑对于每一个点维护子树内与其连通的点的信息.为了换色需要,记录每个点黑白两种情况下子树内连通块的大小. 查询时,找到深度最浅的同色祖先即可,这可以比较简单的树剖+线段树乱搞一下(似乎就是qtree3 ...

  5. SPOJ QTREE Query on a tree VI

    You are given a tree (an acyclic undirected connected graph) with n nodes. The tree nodes are number ...

  6. [BZOJ 3637]Query on a tree VI

    偶然看见了这题,觉得自己 QTREE.COT 什么的都没有刷过的真是弱爆了…… 一道思路很巧妙的题,终于是在约大爷的耐心教导下会了,真是太感谢约大爷了. 这题显然是树链剖分,但是链上维护的东西很恶心. ...

  7. QTREE6&&7 - Query on a tree VI &&VII

    树上连通块 不用具体距离,只询问连通块大小或者最大权值 可以类比Qtree5的方法,但是记录东西很多,例如子树有无0/1颜色等 一个trick,两个LCT分离颜色 每个颜色在边上. 仅保留连通块顶部不 ...

  8. 2019.02.17 spoj Query on a tree VI(链分治)

    传送门 题意简述:给你一棵nnn个黑白点的树,支持改一个点的颜色,询问跟某个点颜色相同的连通块大小. 思路: 还是链分治 233 记fi,0/1f_{i,0/1}fi,0/1​表示iii的所有颜色为0 ...

  9. [CodeChef-QTREE6]Query on a tree VI

    题目大意: 给你一棵黑白树,每个点默认是白色,要求支持以下两种操作: 1.改变一个点的颜色: 2.除去连接不同颜色的点的边,求某个点连通块的大小. 思路: 对原树维护两个树链剖分, 一棵维护当点x为白 ...

随机推荐

  1. 从工具、工具箱到数字化软件工厂——DevOps 设计理念与工程实践专场 | CIF 精彩看点

    西方经典管理理论认为,组织效率可以归为劳动效率.组织效率和人的效率.美国管理学家泰勒所著的<科学管理原理>被德鲁克誉为"20 世纪最伟大的发明",劳动效率说认为分工提升 ...

  2. AT3950 [AGC022E] Median Replace

    题目传送门 Description 有一个长度为 \(n\) 的 \(01\) 串,里面有一些还没有确定,我们标记为 ? .可以进行若干次操作,每次操作可以把三个相邻的数替换成它们的中位数.问有多少种 ...

  3. 题解 [HAOI2012]道路

    题目传送门 题目大意 给出一个 \(n\) 个点 \(m\) 条边的有向图,问每一条边在多少个最短路径中出现. \(n\le 1500,m\le 5000\) 思路 算我孤陋寡闻了... 很显然,我们 ...

  4. SpringBoot之日志注解和缓存优化

    SpringBoot之日志注解和缓存优化 日志注解: 关于SpringBoot中的日志处理,在之前的文章中页写过: 点击进入 这次通过注解+Aop的方式来实现日志的输出: 首先需要定义一个注解类: @ ...

  5. GoLang设计模式10 - 中介者模式

    中介者模式是一种行为型设计模式.在中介者模式中创建了一个中介对象来负责不同类间的通信.因为这些类不需要直接交互,所以也就能避免它们之间的直接依赖,实现解耦的效果. 中介者模式的一个典型案例是老式小火车 ...

  6. 自定义ConditionalOnXX注解

    一.Conditional注解介绍 对SpringBoot有足够了解的小伙伴应该都用过Conditional系列注解,该注解可用在类或者方法上用于控制Bean的初始化. 常用的Conditional注 ...

  7. Golang通脉之结构体

    Go语言中的基础数据类型可以表示一些事物的基本属性,但是要表达一个事物的全部或部分属性时,这时候再用单一的基本数据类型明显就无法满足需求了,Go语言提供了一种自定义数据类型,可以封装多个基本数据类型, ...

  8. 2021 从零开始学Git【新版本Git - 8000字详细介绍】

    我写的这篇文章,主要是记录自己的学习过程,也希望帮助读者少踩坑(比如不同版本可能命令不兼容等).本文面向git零基础初学者,建议读者按照文中命令自己全部操作一遍(注意运行环境). 我的运行环境:win ...

  9. 【技术博客】在Unity3d中实现烟花效果

    在游戏开发中,我们经常需要用到类似烟花的效果.在Unity3d中,实现烟花效果的方法不止一种,我选用了Unity3d中新添加的粒子特效工具--visual effect graph来进行实现. 实现过 ...

  10. BUAA软件工程结对项目作业

    BUAA软件工程结对项目 小组成员:16005001,17373192 1.教学班级和项目地址 项目 内容 这个作业属于哪个课程 博客园班级连接 这个作业的要求在哪里 结对项目作业 我在这个课程的目标 ...