正题

题目链接: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】的更多相关文章

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

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

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

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

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

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

  4. P4332 [SHOI2014]三叉神经树

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

  5. BZOJ 3553: [Shoi2014]三叉神经树 LCT

    犯傻了,想到了如果是 0->1 的话就找最深的非 1 编号,是 1 -> 0 的话就找最深的非 0 编号. 但是没有想到这个东西可以直接维护. 假设不考虑叶子节点,那么如果当前点的值是 1 ...

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

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

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

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

  8. [SHOI2014]三叉神经树

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

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

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

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

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

随机推荐

  1. 关于oracle样例数据库emp、dept、salgrade的mysql脚本复杂查询分析

    大家可以自行网上找资源(网上资源比较多,不建议下载我的),也可以在我这里下载: 1.取得每个部门最高薪水的人员名称:正确   一共有4个单位,要进行左外连接 其中一个单位没得员工 SELECT dep ...

  2. 跟我一起用unity做小地图!

    lol的小地图 转载爬虫请自重,未问先转没排面 不爱多做铺垫,小地图对于一些游戏来说多重要大家都懂,不然你也不会来看我这篇文章的,对不对? 话不多说,开搞! 一.主体功能 一般来说,游戏里的迷你地图都 ...

  3. VS C++ C# 混合编程

    创建C++ DLL 注意,32bit和64bit之间不兼容 创建普通dll工程 设置Properties -> Configuration Properties -> General -& ...

  4. TCP通信的实现代码

    TCP通信 概念 传输控制协议(TCP,Transmission Control Protocol)是一种面向连接的.可靠的.基于字节流的传输层通信协议. 从百科定义中就可以看出,TCP通信的基本条件 ...

  5. JSTL标签报错-http://java.sun.com/jsp/jstl/core

    考虑为tomcat缺少相关的包 导入就好了 导入jstl-api-1.2.jar 以及standard-1.1.2.jar 然后重启服务 更多java学习,请进本人小博客-https://zhangj ...

  6. SQL查询语句执行流程

    msyql执行流程 你有个最简单的表,表里只有一个 ID 字段,在执行下面这个查询语句时:: select * from T where ID=10: 我们看到的只是输入一条语句,返回一个结果,却不知 ...

  7. 【CSS】按钮

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. (一)Superset 1.3图表篇——Table

    本系列文章基于Superset 1.3.0版本.1.3.0版本目前支持分布,趋势,地理等等类型共59张图表.本次1.3版本的更新图表有了一些新的变化,而之前也一直没有做过非常细致的图表教程. 而且目前 ...

  9. 微信支付 V3 开发教程(一):初识 Senparc.Weixin.TenPayV3

    前言 我在 9 年前发布了 Senparc.Weixin SDK 第一个开源版本,一直维护至今,如今 Stras 已经破 7K,这一路上得到了 .NET 社区的积极响应和支持,也受到了非常多的宝贵建议 ...

  10. shell循环之跳出循环

    1.break break命令允许跳出所有循环(终止执行后面的所有循环). 下面的例子中,脚本进入死循环直至用户输入数字大于5.要跳出这个循环,返回到shell提示符下,需要使用break命令. #! ...