洛谷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\) 刚刚发布了引领世界潮流的下一代电子产品-- 概率充电器: "采用全新纳米 ...
随机推荐
- hibernate复习第(二)天
今日要点: 关联映射 多对一(Employee - Department) 一对多(Department - Employee) 一对一(Person - IdCard) 多对多(teachet - ...
- Gym - 100570C: Subrect Query (巧妙的单调队列)
De Prezer loves rectangles.He has a n × m rectangle which there is a number in each of its cells. We ...
- 洛谷P2896 [USACO08FEB]一起吃饭Eating Together
题目描述 The cows are so very silly about their dinner partners. They have organized themselves into thr ...
- 如何利用pyenv 和virtualenv 在单机上搭建多版本python 虚拟开发环境
pyenv 和virtualenv分别是干什么的? pyenv帮助你在一台机上建立多个版本的python环境, 并提供方便的切换方法. virtualenv则就是将一个目录建立为一个虚拟的python ...
- mysql du-master配置
db-server1 my.cnf log_bin = mysql-binbinlog_format = mixedserver_id = 1 read-only = 0#binlog-do-db = ...
- C/C++的区别
C和C++的关系:就像是win98跟winXP的关系.C++是在C的基础上增加了新的理论,玩出了新的花样.所以叫C加加. C和C++的区别: C是一个结构化语言,它的重点在于算法和数据结构.C程序的设 ...
- Qt 按顺序保存多个文件
void MainWindow::on_pushButtonSnap_clicked() { ]; sprintf(image_name, "%s%d%s", "C:/i ...
- union联合体学习
union,中文名“联合体.共用体”,在某种程度上类似结构体struct的一种数据结构,共用体(union)和结构体(struct)同样可以包含很多种数据类型和变量. 不过区别也挺明显: 结构体(st ...
- Matlab数据类型的转换
Matlab中有15种基本数据类型,主要是整型.浮点.逻辑.字符.日期和时间.结构数组.单元格数组以及函数句柄等. 1.整型:(int8:uint8:int16:uint16:int32:uint32 ...
- ubuntu 和 CentOS 安装docker
一.ubuntu14.04 安装docker 1 apt-get update2 apt-get update-grup3 reboot4 检查mapper的安装:ls -l /sys/class/m ...