犯傻了,想到了如果是 0->1 的话就找最深的非 1 编号,是 1 -> 0 的话就找最深的非 0 编号.

但是没有想到这个东西可以直接维护.

假设不考虑叶子节点,那么如果当前点的值是 1 的话要求儿子节点权和 > 1

假设当前从 0->1,那么该叶子造成的影响一定是一条向上的链.

如果向上走到某一时刻,该点的儿子权和不等于 1,那么这个点及以上就影响不到了.

如果权和为 2,那么在 0->1 之前就已经是 1 了,修改后也肯定还是 1.

如果权和为 0,那么在 0->1 之后顶多能把权和+1,所以做的时无用功.

所以,会造成影响的是以该叶子向上延伸的最长的全 1 链.

这些点全部会从 0 变成 1,然后做一个区间 +1 (全变成 2)

这里讲一下区间加的时候如何维护标记:

因为我们进行区间加的链肯定是全 1 / 2 的.

所以说,原来是全 1 的话原来的 1 的最深节点就消失,然后最深度节点是 2 的就会新产生.

然后你发现正好是 1->2, 2->0 或者 2->1, 1->0,所以直接交换一下 1 和 2 的编号即可.

#include <bits/stdc++.h>
using namespace std;
#define N 1600000
#define lson t[x].ch[0]
#define rson t[x].ch[1]
#define get(x) (t[t[x].f].ch[1]==x)
#define isrt(x) (!(t[t[x].f].ch[0]==x||t[t[x].f].ch[1]==x))
#define setIO(s) freopen(s".in","r",stdin)
int n,m,edges;
int hd[N],to[N],nex[N],sta[N];
struct node
{
int ch[2],id[3],f,add,val,sum;
}t[N];
inline void mark(int x,int add)
{
if(!x) return;
t[x].sum+=add,t[x].val=t[x].sum>1;
swap(t[x].id[1],t[x].id[2]);
t[x].add+=add;
}
inline void pushup(int x)
{
t[x].id[1]=t[rson].id[1];
t[x].id[2]=t[rson].id[2];
if(!t[x].id[1])
{
if(t[x].sum!=1) t[x].id[1]=x;
else t[x].id[1]=t[lson].id[1];
}
if(!t[x].id[2])
{
if(t[x].sum!=2) t[x].id[2]=x;
else t[x].id[2]=t[lson].id[2];
}
}
inline void pushdown(int x)
{
if(t[x].add)
{
if(lson) mark(lson,t[x].add);
if(rson) mark(rson,t[x].add);
t[x].add=0;
}
}
inline void rotate(int x)
{
int old=t[x].f,fold=t[old].f,which=get(x);
if(!isrt(old)) t[fold].ch[t[fold].ch[1]==old]=x;
t[old].ch[which]=t[x].ch[which^1],t[t[old].ch[which]].f=old;
t[x].ch[which^1]=old,t[old].f=x,t[x].f=fold;
pushup(old),pushup(x);
}
void splay(int x)
{
int u=x,v=0,fa;
for(sta[++v]=u;!isrt(u);u=t[u].f) sta[++v]=t[u].f;
for(;v;--v) pushdown(sta[v]);
for(u=t[u].f;(fa=t[x].f)!=u;rotate(x))
{
if(t[fa].f!=u)
{
rotate(get(fa)==get(x)?fa:x);
}
}
}
inline void Access(int x)
{
for(int y=0;x;y=x,x=t[x].f)
{
splay(x);
rson=y;
pushup(x);
}
}
void add(int u,int v)
{
nex[++edges]=hd[u],hd[u]=edges,to[edges]=v;
}
void dfs(int u)
{
for(int i=hd[u];i;i=nex[i]) dfs(to[i]),t[u].sum+=t[to[i]].val;
if(u<=n) t[u].val=t[u].sum>1;
}
int main()
{
// setIO("input");
int i,j,Q;
scanf("%d",&n);
for(i=1;i<=n;++i)
{
for(j=1;j<=3;++j)
{
int x;
scanf("%d",&x),add(i,x),t[x].f=i;
}
}
for(i=n+1;i<=3*n+1;++i) scanf("%d",&t[i].val);
dfs(1);
scanf("%d",&Q);
int ans=t[1].val;
while(Q--)
{
int x;
scanf("%d",&x);
int tag=(t[x].val?-1:1),y=t[x].f;
Access(y),splay(y);
int w=t[y].id[t[x].val?2:1];
if(w)
{
splay(w);
mark(t[w].ch[1],tag);
pushup(t[w].ch[1]);
t[w].sum+=tag;
t[w].val=t[w].sum>1;
pushup(w);
}
else
{
ans^=1;
mark(y,tag);
pushup(y);
}
t[x].val^=1;
printf("%d\n",ans);
}
return 0;
}

  

BZOJ 3553: [Shoi2014]三叉神经树 LCT的更多相关文章

  1. [BZOJ 3553][SHOI2014]三叉神经树

    传送门(下面也有题面) 题目大意: 一颗有根树,每个非叶子节点都有三个子节点,每个节点的权为0/1. 每个节点的权 取决于其所有子节点中 哪种权出现的次数更多. 有若干次询问,每次询问修改一个叶子节点 ...

  2. P4332 [SHOI2014]三叉神经树(LCT)

    Luogu4332 LOJ2187 题解 代码-Tea 题意 : 每个点有三个儿子 , 给定叶节点的权值\(0\)或\(1\)且支持修改 , 非叶子节点的权值为当有\(>=2\)个儿子的权值为\ ...

  3. 3553: [Shoi2014]三叉神经树(树链剖分)

    这道题特别恶心,首先我们可以发现更改的就是出现连续的一或二,那么就用线段树+树链剖分找到这个范围 想到是不难想,就是打起来恶心罢了= = CODE: #include<cstdio> #i ...

  4. 洛谷P4332 [SHOI2014]三叉神经树(LCT,树剖,二分查找,拓扑排序)

    洛谷题目传送门 你谷无题解于是来补一发 随便百度题解,发现了不少诸如树剖\(log^3\)LCT\(log^2\)的可怕描述...... 于是来想想怎么利用题目的性质,把复杂度降下来. 首先,每个点的 ...

  5. 洛谷4322 SHOI2014 三叉神经树(LCT+思维)

    好久之前做的题了QWQ 现在来补一发博客 一道神仙题啊..qwq 首先,我们可以看出来,我们如果对于每个点维护一个\(val\),表示他的直系儿子中有几个表现为1的. 那么\(val[x]>&g ...

  6. 洛谷P4332 [SHOI2014]三叉神经树(LCT)

    传送门 FlashHu大佬太强啦%%% 首先,我们可以根据每一个点的权值为$1$的儿子的个数把每个点记为$0~3$,表示这一个点的点权 先考虑一下暴力的过程,假设从$0$变为$1$,先更改一个叶子结点 ...

  7. [SHOI2014]三叉神经树

    题目描述 计算神经学作为新兴的交叉学科近些年来一直是学术界的热点.一种叫做SHOI 的神经组织因为其和近日发现的化合物 SHTSC 的密切联系引起了人们的极大关注. SHOI 组织由若干个 SHOI ...

  8. BZOJ3553 : [Shoi2014]三叉神经树

    设val[i]为i连出去的树突中输出值为0的个数 如果val[x]<=1,输出值为1,否则输出值为0 修改x就相当于val[f[i]]++或者val[f[i]]-- 用Link-cut Tree ...

  9. P4332 [SHOI2014]三叉神经树

    \(\color{#0066ff}{ 题目描述 }\) 计算神经学作为新兴的交叉学科近些年来一直是学术界的热点.一种叫做SHOI 的神经组织因为其和近日发现的化合物 SHTSC 的密切联系引起了人们的 ...

随机推荐

  1. 使用 EnumWindows 找到满足你要求的窗口

    原文:使用 EnumWindows 找到满足你要求的窗口 在 Windows 应用开发中,如果需要操作其他的窗口,那么可以使用 EnumWindows 这个 API 来枚举这些窗口. 本文介绍使用 E ...

  2. SSM前后端分离 ssm+html+js(ajax) 这种controll层的返回值是结合或者网址

    提示: 1.单表查询多条数据用 list<实体类名字> mapper层 1.1单表查询单条数据用  对象 2.两表关联查多条 list<map<String,Object> ...

  3. java之spring mvc之Restful风格开发及相关的配置

    1. Restful : 表征状态状态转移. 传统 : url : http://localhost:8080/usersys/delete.do?user.id=12 Restful 风格:url ...

  4. Python的字符串函数

    今天用了将近一天的时间去学习Python字符串函数 上午学了17个,下午学了23个(共计40) 详细内容请见菜鸟教程--Python3字符串--Python的字符串内建函数

  5. CSP J/S 2019受虐记

    一枚蒟蒻的游记~ 提高组DAY1 不是说每场考试都有一道签到题吗 那我tm读了三遍题硬是没找到一道水题是怎么回事(是我太弱了吗) 没办法,硬着头皮做T1 暴力写法...期望得分30pts 于是...在 ...

  6. 【转载】C#中int.TryParse方法和int.Parse方法的异同之处

    在C#编程过程中,int.TryParse方法和int.Parse方法都可以将字符串string转换为整型int类型,但两者还是有区别,最重要的区别在于int.TryParse方法在字符串无法转换为i ...

  7. C# 认识 接口

    一.什么是接口 C#接口中包含方法.属性.索引器和事件的声明,但常用的接口中一般就是方法和属性,然而接口中并没有方法的具体实现代码(不能提供任何成员实现),只有方法的返回类型和方法名.一个类实现了某个 ...

  8. CASE WHEN 函数

    --Case函数: --有两种格式: -- 1.简单Case函数. -- 2.Case搜索函数. --1.简单Case函数: -- CASE [COLUMN_NAME] -- WHEN ['条件参数' ...

  9. Arm Qt编译Qt例程出错 GLES3/gl3.h: No such file or directory 解决方法

    工作环境 PC:Ubuntu18.04QtCreator: 4.8.2交叉编译环境:野火imxull6开发板提供的 5-编译工具链->qt交叉编译工具 在之前博客配置成功的交叉编译环境,编译Qt ...

  10. python爬取数据分析

    一.python爬虫使用的模块 1.import requests 2.from bs4 import BeautifulSoup 3.pandas 数据分析高级接口模块 二. 爬取数据在第一个请求中 ...