P4332-[SHOI2014]三叉神经树【LCT】
正题
题目链接:https://www.luogu.com.cn/problem/P4332
题目大意
给出\(n\)个点的一棵有根三叉树,保证每个点的儿子个数为\(3\)或者\(0\),每个叶子有一个权值\(0\)或\(1\),每个非叶子节点的权值是它儿子中权值较多的那个,每次修改一个叶子的权值,求根节点的权值。
\(1\leq n,q\leq 5\times 10^5\)
解题思路
修改一个节点会影响的权值显然是它到根节点路径上的一个前缀。
然后考虑什么样的节点会受到影响,如果\(0\)改为\(1\)那么一路上原来恰好为两个\(0\)的节点就会被修改,那么我们的思路是考虑找到这条路径上第一个\(1\)的个数不为\(1\)的节点。
而且考虑上修改的话十分的麻烦,因为\(O(n\log^2 n)\)过不去所以不考虑树剖,可以考虑一下\(LCT\)。
我们可以先联通修改点到根的节点,然后在\(Splay\)上二分出第一个不为\(1\)的节点,然后对于它和它的右子树暴力修改即可。
\(1\)改为\(0\)同理,维护第一个不为\(2\)的节点即可。
时间复杂度\(O(n\log n)\)
code
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<stack>
using namespace std;
const int N=2e6+10;
int n,m,ans,fa[N],v[N],w1[N],w2[N],lazy[N],t[N][2];
vector<int> G[N];stack<int> s;
bool Nroot(int x)
{return fa[x]&&(t[fa[x]][0]==x||t[fa[x]][1]==x);}
bool Direct(int x)
{return t[fa[x]][1]==x;}
void PushUp(int x){
if(w1[t[x][1]])w1[x]=w1[t[x][1]];
else if(v[x]!=1)w1[x]=x;
else w1[x]=w1[t[x][0]];
if(w2[t[x][1]])w2[x]=w2[t[x][1]];
else if(v[x]!=2)w2[x]=x;
else w2[x]=w2[t[x][0]];
return;
}
void PushR(int x,int w)
{v[x]^=3;swap(w1[x],w2[x]);lazy[x]+=w;return;}
void PushDown(int x){
if(!lazy[x])return;
PushR(t[x][0],lazy[x]);
PushR(t[x][1],lazy[x]);
lazy[x]=0;return;
}
void Rotate(int x){
int y=fa[x],z=fa[y];
int xs=Direct(x),ys=Direct(y);
int w=t[x][xs^1];
if(Nroot(y))t[z][ys]=x;
t[x][xs^1]=y;t[y][xs]=w;
if(w)fa[w]=y;fa[y]=x;fa[x]=z;
PushUp(y);PushUp(x);return;
}
void Splay(int x){
int y=x;s.push(x);
while(Nroot(y))y=fa[y],s.push(y);
while(!s.empty())PushDown(s.top()),s.pop();
while(Nroot(x)){
y=fa[x];
if(!Nroot(y))Rotate(x);
else if(Direct(x)==Direct(y))
Rotate(y),Rotate(x);
else Rotate(x),Rotate(x);
}
return;
}
void Access(int x){
for(int y=0;x;y=x,x=fa[x])
Splay(x),t[x][1]=y,PushUp(x);
return;
}
void Updata(int x){
int op=(v[x]^=2);
x=fa[x];Access(x);Splay(x);
if(op){
if(w1[x]){
x=w1[x];Splay(x);
PushR(t[x][1],1);PushUp(t[x][1]);
v[x]++;PushUp(x);
}
else ans=!ans,PushR(x,1),PushUp(x);
}
else{
if(w2[x]){
x=w2[x];Splay(x);
PushR(t[x][1],-1);PushUp(t[x][1]);
v[x]--;PushUp(x);
}
else ans=!ans,PushR(x,-1),PushUp(x);
}
return;
}
void dfs(int x){
for(int i=0;i<G[x].size();i++){
int y=G[x][i];dfs(y);
v[x]+=(v[y]>>1);
}
PushUp(x);
return;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
fa[x]=fa[y]=fa[z]=i;
G[i].push_back(x);
G[i].push_back(y);
G[i].push_back(z);
}
for(int i=n+1;i<=3*n+1;i++)
scanf("%d",&v[i]),v[i]<<=1;
dfs(1);ans=v[1]>>1;
scanf("%d",&m);
while(m--){
int x;scanf("%d",&x);
Updata(x);
printf("%d\n",ans);
}
return 0;
}
P4332-[SHOI2014]三叉神经树【LCT】的更多相关文章
- P4332 [SHOI2014]三叉神经树(LCT)
Luogu4332 LOJ2187 题解 代码-Tea 题意 : 每个点有三个儿子 , 给定叶节点的权值\(0\)或\(1\)且支持修改 , 非叶子节点的权值为当有\(>=2\)个儿子的权值为\ ...
- 洛谷P4332 [SHOI2014]三叉神经树(LCT,树剖,二分查找,拓扑排序)
洛谷题目传送门 你谷无题解于是来补一发 随便百度题解,发现了不少诸如树剖\(log^3\)LCT\(log^2\)的可怕描述...... 于是来想想怎么利用题目的性质,把复杂度降下来. 首先,每个点的 ...
- 洛谷P4332 [SHOI2014]三叉神经树(LCT)
传送门 FlashHu大佬太强啦%%% 首先,我们可以根据每一个点的权值为$1$的儿子的个数把每个点记为$0~3$,表示这一个点的点权 先考虑一下暴力的过程,假设从$0$变为$1$,先更改一个叶子结点 ...
- P4332 [SHOI2014]三叉神经树
\(\color{#0066ff}{ 题目描述 }\) 计算神经学作为新兴的交叉学科近些年来一直是学术界的热点.一种叫做SHOI 的神经组织因为其和近日发现的化合物 SHTSC 的密切联系引起了人们的 ...
- BZOJ 3553: [Shoi2014]三叉神经树 LCT
犯傻了,想到了如果是 0->1 的话就找最深的非 1 编号,是 1 -> 0 的话就找最深的非 0 编号. 但是没有想到这个东西可以直接维护. 假设不考虑叶子节点,那么如果当前点的值是 1 ...
- [BZOJ 3553][SHOI2014]三叉神经树
传送门(下面也有题面) 题目大意: 一颗有根树,每个非叶子节点都有三个子节点,每个节点的权为0/1. 每个节点的权 取决于其所有子节点中 哪种权出现的次数更多. 有若干次询问,每次询问修改一个叶子节点 ...
- 洛谷4322 SHOI2014 三叉神经树(LCT+思维)
好久之前做的题了QWQ 现在来补一发博客 一道神仙题啊..qwq 首先,我们可以看出来,我们如果对于每个点维护一个\(val\),表示他的直系儿子中有几个表现为1的. 那么\(val[x]>&g ...
- [SHOI2014]三叉神经树
题目描述 计算神经学作为新兴的交叉学科近些年来一直是学术界的热点.一种叫做SHOI 的神经组织因为其和近日发现的化合物 SHTSC 的密切联系引起了人们的极大关注. SHOI 组织由若干个 SHOI ...
- BZOJ3553 : [Shoi2014]三叉神经树
设val[i]为i连出去的树突中输出值为0的个数 如果val[x]<=1,输出值为1,否则输出值为0 修改x就相当于val[f[i]]++或者val[f[i]]-- 用Link-cut Tree ...
- 3553: [Shoi2014]三叉神经树(树链剖分)
这道题特别恶心,首先我们可以发现更改的就是出现连续的一或二,那么就用线段树+树链剖分找到这个范围 想到是不难想,就是打起来恶心罢了= = CODE: #include<cstdio> #i ...
随机推荐
- C++ native 转 C++的CLI
- SpringBoot中自定义错误页面
错误页面定制(在有模板引擎的情况下): 有模板的支持下: 在templates文件夹下 建立 error文件夹 在error文件夹下 404.html 500.html 4xx.html (名字就叫4 ...
- 统计MySQL数据库硬盘占用量大小
select TABLE_NAME, concat(truncate(data_length/1024/1024,2),' MB') as data_size, concat(truncate(ind ...
- 哈希表(HashMap)分析及实现(JAVA)
转自:http://www.java3z.com/cwbwebhome/article/article8/83560.html?id=4649 探讨Hash表中的一些原理/概念,及根据这些原理/概念, ...
- 交互式查询⼯具Impala
Impala是什么: Impala是Cloudera提供的⼀款开源的针对HDFS和HBASE中的PB级别数据进⾏交互式实时查询(Impala 速度快),Impala是参照⾕歌的新三篇论⽂当中的Drem ...
- 高德渲染网关Go语言重构实践
1.导读 高德启动Go业务建设已经有段时间了,主要包含Go应用落地,Go中间件建设,云原生三个部分.经过持续的发力,在这些方面取得了不错的进展.高德Go业务落地过程是如何实现的,遇到过哪些问题,如何 ...
- k8s 探针 exec多个判断条件条件 多个检测条件
背景 1,之前我们的yaml文件里面有就绪探针. 2,探针是检测一个文件是否生成,生成了说明服务正常. 3,现在要加一个检测,也是一个文件是否存在并且不为空. 4,只有两个条件同时满足了 服务才算正常 ...
- C# - 音乐小闹钟_BetaV2.0
时间:2017-11-21 作者:byzqy 介绍: 虽然上一版本基本实现了闹钟的功能,但是界面.功能.用户体验(简直谈不上体验^_^),以及众多的bug,所以升级,刻不容缓! 还是先看一下Beta ...
- css写法
id选择器 > 类选择器 > 标签选择器 @charset "utf-8"; charset=utf-8 表示当前文档的字符集是采用utf-8的字符,也就是我们常说 ...
- ucosii操作系统内核源码学习第一篇
根据书本理论介绍以及实际看内核源代码得出: 1. 操作系统默认定义了64个TCB块(为全局变量,编译时候以及分配了,创建一个任务就使用一个,删除一个任务就归还一个)(为什么最大只支持64个任务呢,我们 ...