洛谷P4332 [SHOI2014]三叉神经树(LCT)
FlashHu大佬太强啦%%%
首先,我们可以根据每一个点的权值为$1$的儿子的个数把每个点记为$0~3$,表示这一个点的点权
先考虑一下暴力的过程,假设从$0$变为$1$,先更改一个叶子结点,然后不断地往上更新,如果更改之后父亲的儿子中权值为$1$的儿子个数大于权值为$0$的儿子个数,那么就继续更新父亲,直到不能更新为止
不难发现,我们每一个更改的都是树上的一条链。而且,只有当点权为$1$时,才能因为修改使点权变为$2$,使输出改变,从而更新祖先。那么,我们需要的就是对于每一个节点,从它向上的连续的点权为$1$的一部分
如果是从$1$变为$0$同理,我们要维护从每一个节点向上的连续的点权为$2$的一部分
那么我们对于每一个节点,先access,然后记录splay中最深的点权不为$1$和$2$的点,然后把它给splay到根,再对右子树进行区间修改,对他自己单点修改
然后注意特判,如果整棵splay里都没有点权不为$1$或$2$的点,那么直接区间修改
然后怎么记录点权嘞?我们先把所有叶子结点的值*2,那么只有0和2两种值,然后每一个节点只要加上它所有叶子结点的值/2就是这个点的点权了
//minamoto
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[<<],*p1=buf,*p2=buf;
inline int read(){
#define num ch-'0'
char ch;bool flag=;int res;
while(!isdigit(ch=getc()))
(ch=='-')&&(flag=true);
for(res=num;isdigit(ch=getc());res=res*+num);
(flag)&&(res=-res);
#undef num
return res;
}
char sr[<<];int C=-;
inline void Ot(){fwrite(sr,,C+,stdout),C=-;}
inline void print(int x){
sr[++C]=x|,sr[++C]='\n';
}
const int N=,M=;
int fa[M],ch[N][],n1[N],n2[N],tag[N],v[M];
int d[N],q[M],h=,t,ans;
#define ls ch[x][0]
#define rs ch[x][1]
inline bool isrt(int x){return ch[fa[x]][]!=x&&ch[fa[x]][]!=x;}
inline void pup(int x){
//先右儿子再自己最后左儿子
//因为&是短路运算符,有一个为假就会自动跳出
if(!(n1[x]=n1[rs])&&!(n1[x]=x*(v[x]!=))) n1[x]=n1[ls];
if(!(n2[x]=n2[rs])&&!(n2[x]=x*(v[x]!=))) n2[x]=n2[ls];
}
inline void pdown(int x,int t){
//被区间修改的要么都是1要么都是2,直接反转信息
v[x]^=,swap(n1[x],n2[x]),tag[x]+=t;
}
void all(int x){
if(!isrt(x)) all(fa[x]);
if(tag[x]) pdown(ls,tag[x]),pdown(rs,tag[x]),tag[x]=;
}
void rotate(int x){
int y=fa[x],z=fa[y],d=ch[y][]==x;
if(!isrt(y)) ch[z][ch[z][]==y]=x;
fa[x]=z,fa[y]=x,fa[ch[x][d^]]=y,ch[y][d]=ch[x][d^],ch[x][d^]=y,pup(y);
}
void splay(int x){
all(x);
for(int y=fa[x],z=fa[y];!isrt(x);y=fa[x],z=fa[y]){
if(!isrt(y))
((ch[y][]==x)^(ch[z][]==y))?rotate(x):rotate(y);
rotate(x);
}
pup(x);
}
inline void access(int x){
for(int y=;x;x=fa[y=x])
splay(x),rs=y,pup(x);
}
int main(){
// freopen("testdata.in","r",stdin);
int n=read();
for(int i=;i<=n;++i)
d[fa[read()]=fa[read()]=fa[read()]=i]=;
for(int i=n+;i<=*n+;++i) v[q[++t]=i]=read()<<;
while(h<=t){
int x=q[h++];if(x<=n) pup(x);
v[fa[x]]+=v[x]>>;
if(!(--d[fa[x]])) q[++t]=fa[x];
}
ans=v[]>>;
int q=read();
while(q--){
int x=read(),k=(v[x]^=)-;
access(x=fa[x]),splay(x);
if(~k?n1[x]:n2[x]){
splay(x=(~k?n1[x]:n2[x]));
pdown(rs,k),pup(rs);
v[x]+=k,pup(x);
}
else pdown(x,k),pup(x),ans^=;
print(ans);
}
Ot();
return ;
}
洛谷P4332 [SHOI2014]三叉神经树(LCT)的更多相关文章
- 洛谷P4332 [SHOI2014]三叉神经树(LCT,树剖,二分查找,拓扑排序)
洛谷题目传送门 你谷无题解于是来补一发 随便百度题解,发现了不少诸如树剖\(log^3\)LCT\(log^2\)的可怕描述...... 于是来想想怎么利用题目的性质,把复杂度降下来. 首先,每个点的 ...
- 洛谷4322 SHOI2014 三叉神经树(LCT+思维)
好久之前做的题了QWQ 现在来补一发博客 一道神仙题啊..qwq 首先,我们可以看出来,我们如果对于每个点维护一个\(val\),表示他的直系儿子中有几个表现为1的. 那么\(val[x]>&g ...
- P4332 [SHOI2014]三叉神经树(LCT)
Luogu4332 LOJ2187 题解 代码-Tea 题意 : 每个点有三个儿子 , 给定叶节点的权值\(0\)或\(1\)且支持修改 , 非叶子节点的权值为当有\(>=2\)个儿子的权值为\ ...
- P4332 [SHOI2014]三叉神经树
\(\color{#0066ff}{ 题目描述 }\) 计算神经学作为新兴的交叉学科近些年来一直是学术界的热点.一种叫做SHOI 的神经组织因为其和近日发现的化合物 SHTSC 的密切联系引起了人们的 ...
- BZOJ 3553: [Shoi2014]三叉神经树 LCT
犯傻了,想到了如果是 0->1 的话就找最深的非 1 编号,是 1 -> 0 的话就找最深的非 0 编号. 但是没有想到这个东西可以直接维护. 假设不考虑叶子节点,那么如果当前点的值是 1 ...
- 洛谷P3373 [模板]线段树 2(区间增减.乘 区间求和)
To 洛谷.3373 [模板]线段树2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.将某区间每一个数乘上x 3.求出某区间每一个数的和 输入输出格式 输入格 ...
- 【BZOJ2830/洛谷3830】随机树(动态规划)
[BZOJ2830/洛谷3830]随机树(动态规划) 题面 洛谷 题解 先考虑第一问. 第一问的答案显然就是所有情况下所有点的深度的平均数. 考虑新加入的两个点,一定会删去某个叶子,然后新加入两个深度 ...
- [BZOJ 3553][SHOI2014]三叉神经树
传送门(下面也有题面) 题目大意: 一颗有根树,每个非叶子节点都有三个子节点,每个节点的权为0/1. 每个节点的权 取决于其所有子节点中 哪种权出现的次数更多. 有若干次询问,每次询问修改一个叶子节点 ...
- 洛谷 P4284 [SHOI2014]概率充电器 概率与期望+换根DP
洛谷 P4284 [SHOI2014]概率充电器 概率与期望+换根DP 题目描述 著名的电子产品品牌\(SHOI\) 刚刚发布了引领世界潮流的下一代电子产品-- 概率充电器: "采用全新纳米 ...
随机推荐
- STL list链表的用法详解
本文以List容器为例子,介绍了STL的基本内容,从容器到迭代器,再到普通函数,而且例子丰富,通俗易懂.不失为STL的入门文章,新手不容错过! 0 前言 1 定义一个list 2 使用list的成员函 ...
- hibernate 一级缓存、二级缓存
一级缓存:——session一旦关掉就没有了.使用 load和get加载对象的时候,会自动加载到缓存,读取的也会读缓存. public void huancun(){ Session session= ...
- python--17个新手常见Python运行时错误
当初学 Python 时,想要弄懂 Python 的错误信息的含义可能有点复杂.这里列出了常见的的一些让你程序 crash 的运行时错误. 1)忘记在 if , elif , else , for , ...
- 异常之: The server time zone value '�й���ʱ��' is unrecognized or represents more than one time zone.
在 MySQL 中执行命令试下: set global time_zone=’+8:00’ 设置为东8区 就不报错了. show variables like '%time_zone%'; 解释:在 ...
- linux命令学习笔记(35):ln 命令
ln是linux中又一个非常重要命令,它的功能是为某一个文件在另外一个位置建立一个同步的链接.当我们需要在 不同的目录,用到相同的文件时,我们不需要在每一个需要的目录下都放一个必须相同的文件,我们只要 ...
- Android模拟器adb命令介绍
在SDK的Tools文件夹下包含着Android模拟器操作的重要命令adb,adb的全称为Android Debug Bridge,就是调试桥的作用 在SDK的Tools文件夹下包含着Android模 ...
- [原]NYOJ-组合数-32
大学生程序代写 http://acm.nyist.net/JudgeOnline/problem.php?pid=32 /*组合数 时间限制:3000 ms | 内存限制:65535 KB 难度: ...
- vmware station中 UDEV 无法获取共享存储磁盘的UUID,症状: scsi_id -g -u -d /dev/sdb 无返回结果。
1.确认在所有RAC节点上已经安装了必要的UDEV包 [root@11gnode1 ~]# rpm -qa|grep udevsystem-config-printer-udev-1.1.16-25. ...
- 使用Visual Studio进行单元测试-Part4
本文主要介绍Visual Studio(2012+)单元测试框架的一些技巧: 如何模拟类的构造函数 优化代码,便于测试 一.如何模拟类的构造函数 1.1 被测代码 基础代码,IShape分别有Rect ...
- bzoj 2178 圆的面积并 —— 辛普森积分
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2178 先看到这篇博客:https://www.cnblogs.com/heisenberg- ...