好久之前做的题了QWQ

现在来补一发博客

一道神仙题啊。。qwq

首先,我们可以看出来,我们如果对于每个点维护一个\(val\),表示他的直系儿子中有几个表现为1的。

那么\(val[x]>>1\) 就是他反应的类型

这样十分便于我们计算一开始的\(val\)

那么考虑修改。

一定是会修改一条\(连续1(对应着0->1),或者连续2(1->0)\)

也就是说,如果我们能够知道一次修改,\(1到x\)的路径下最下面的1或者2的位置,我们就能够通过链修改来实现。

其实一开始我想的是二分

我们发现,可以通过\(LCT\)维护最深的不是\(1\)的位置和不是\(2\)的位置\(num1和num2\)

那么我们对于一次修改,假设由\(0修改成1\)

如果\(num1==0\),那么说明整条链都会被修改,直接修改整条路径

不然,我们就将路径提出来,\(splay(num1)\)之后,修改他的右儿子,表示他下面的点。

然后把当前点的\(val\)修改,但是不改变别的量。

QWQ有一些细节,对于修改的时候,由于路径上的\(val\)都是1或者2。

所以修改的之后可以直接\(xor\ 2\)

具体细节看代码实现吧

里面有详细的注释

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
#include<cmath>
#include<map>
#include<set>
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while (!isdigit(ch)) {if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
const int maxn = 2e6+1e2;
int ch[maxn][3];
int fa[maxn],val[maxn];
int tag[maxn];
int n,m;
int num1[maxn],num2[maxn]; //深度最深的 儿子数不为1 或者 2 的 节点是的编号
int st[maxn];
int son(int x)
{
if (ch[fa[x]][0]==x) return 0;
else return 1;
}
bool notroot(int x)
{
return ch[fa[x]][0]==x || ch[fa[x]][1]==x;
}
void update(int x) //由于是深度最深,我们一定是先考虑右子树,再说当前点,再是右子树
{
num1[x]=num1[ch[x][1]];
if (!num1[x] && val[x]!=1) num1[x]=x;
if (!num1[x]) num1[x]=num1[ch[x][0]];
num2[x]=num2[ch[x][1]];
if (!num2[x] && val[x]!=2) num2[x]=x;
if (!num2[x]) num2[x]=num2[ch[x][0]];
}
void solve(int x,int d)
{
val[x]^=3;
swap(num1[x],num2[x]); //修改的时候,必定是一段全为1或者2的区间,所以一个一定是0,直接交换是没错的
tag[x]+=d;
}
void pushdown(int x)
{
if (tag[x])
{
if (ch[x][0]) solve(ch[x][0],tag[x]);
if (ch[x][1]) solve(ch[x][1],tag[x]);
tag[x]=0;
}
}
void rotate(int x)
{
int y=fa[x],z=fa[y];
int b=son(x),c=son(y);
if (notroot(y)) ch[z][c]=x;
fa[x]=z;
ch[y][b]=ch[x][!b];
fa[ch[x][!b]]=y;
ch[x][!b]=y;
fa[y]=x;
update(y);
update(x);
}
void splay(int x)
{
int y=x,cnt=0;
st[++cnt]=y;
while (notroot(y)) y=fa[y],st[++cnt]=y;
while (cnt) pushdown(st[cnt--]);
while (notroot(x))
{
int y=fa[x],z=fa[y];
int b=son(x),c=son(y);
if (notroot(y))
{
if (b==c) rotate(y);
else rotate(x);
}
rotate(x);
}
update(x);
}
void access(int x)
{
for (int y=0;x;y=x,x=fa[x])
{
splay(x);
ch[x][1]=y;
update(x);
}
}
int in[maxn];
queue<int> q;
int main()
{
n=read();
for (int i=1;i<=n;i++)
{
int x=read(),y=read(),w=read();
in[i]=3;
fa[x]=fa[y]=fa[w]=i;
}
for (int i=n+1;i<=3*n+1;i++) val[i]=read()*2,q.push(i); //我们事先val都*2,那么对于每个点,他表现出来的特征就是val>>1
int m=read();
while (!q.empty()) //拓扑排序先预处理出来每个点的val
{
int x=q.front();
q.pop();
if (x<=n) update(x);
val[fa[x]]+=val[x]/2;
in[fa[x]]--;
if (!in[fa[x]]) q.push(fa[x]);
}
int ans=val[1]>>1;
//在本题中,val表示儿子的表示1的数量,那么val>>1就相当于每个点表达的信息
for (int i=1;i<=m;i++)
{
int x=read();
val[x]^=2; //叶子节点只有可能是0或者1,而乘2之后就是0或者2
int k = val[x] - 1;
x=fa[x]; //不修改底下的叶子节点
access(x);
splay(x); //打通这个点到1的路径
int now;
if (k==-1) now = num2[x];
else now = num1[x];
if (!now)
{
solve(x,k);
update(x);
ans^=1;
}
else
{
splay(now);
solve(ch[now][1],k);
update(ch[now][1]);
val[now]+=k;
update(now);
}
cout<<ans<<"\n";
}
return 0;
}

洛谷4322 SHOI2014 三叉神经树(LCT+思维)的更多相关文章

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

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

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

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

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

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

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

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

  5. 洛谷P3373 [模板]线段树 2(区间增减.乘 区间求和)

    To 洛谷.3373 [模板]线段树2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.将某区间每一个数乘上x 3.求出某区间每一个数的和 输入输出格式 输入格 ...

  6. 【BZOJ2830/洛谷3830】随机树(动态规划)

    [BZOJ2830/洛谷3830]随机树(动态规划) 题面 洛谷 题解 先考虑第一问. 第一问的答案显然就是所有情况下所有点的深度的平均数. 考虑新加入的两个点,一定会删去某个叶子,然后新加入两个深度 ...

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

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

  8. 洛谷 P4284 [SHOI2014]概率充电器 概率与期望+换根DP

    洛谷 P4284 [SHOI2014]概率充电器 概率与期望+换根DP 题目描述 著名的电子产品品牌\(SHOI\) 刚刚发布了引领世界潮流的下一代电子产品-- 概率充电器: "采用全新纳米 ...

  9. 洛谷AT2342 Train Service Planning(思维,动态规划,珂朵莉树)

    洛谷题目传送门 神仙思维题还是要写点东西才好. 建立数学模型 这种很抽象的东西没有式子描述一下显然是下不了手的. 因为任何位置都以\(k\)为周期,所以我们只用关心一个周期,也就是以下数都在膜\(k\ ...

随机推荐

  1. vscode如何配置ts的lint,如何配置才能让eslint和prettier不冲突一键格式化代码(vue开发使用)

    最近在使用ts,发觉tslint在vscode上使用很不方便,不如eslint一键格式化高效,就想着能不能配置下vscode让其像写js一样爽 这篇文章主要解决2个问题,第一个是如何让vscode使用 ...

  2. PB代码转JAVA工具

    开发了PB代码转JAVA的工具,正在做datawindow和datastore的处理.以下是目前已经能处理的功能: 1.自动从PBL中获取对象的函数或事件代码 a)可以自动获取实例变量.函数或事件的入 ...

  3. MVVM框架三巨头之Vue的前世今生。

    前端有三宝,Angular,Vue,React.目前这三大主流JS框架已经成三分之势.其中的React框架是由脸书开发的,今天我们就来聊一聊VueJS的前世今生. 前世 在2013年的js开发者大会上 ...

  4. Faiss使用多线程出现的性能问题

    Faiss使用多线程出现的性能问题 faiss在增加CPU的情况下,反而出现效率低下的问题. 从理论上看,作为一个CPU/GPU计算型的应用,更多的核意味着更大的计算吞吐能力,性能只会越来越好才是. ...

  5. 温故知新:老铁,WeakReference了解一下?

    本文供稿--大师兄 弱引用是个什么鬼?大白话说就是不那么强的引用(哈哈,纯属玩笑,实际可不是这样滴),那强引用又是个什么鬼?他们有什么用处?问题有点迷,君阅完这篇文章后或许你心中就有答案了-- 什么是 ...

  6. Ajax的GET,POST方法传输数据和接收返回数据

    //首先创建一个Ajax对象 function ajaxFunction(){ var xmlHttp; try{ // Firefox, Opera 8.0+, Safari xmlHttp=new ...

  7. 那些优秀的python代码

    时间:2019-04-18 收藏:PangYuaner 标题:Python如何生成树形图案 地址:https://www.jb51.net/article/132049.htm 标题:用python- ...

  8. Mysql基本知识整理

    一.简介 1.什么是数据库? 数据库(Database)是按照数据结构来组织.存储和管理数据的仓库,每个数据库都有一个或多个不同的API用于创建,访问,管理,搜索和复制所保存的数据. 2.关系型数据库 ...

  9. BUUCTF-[网鼎杯 2020 青龙组]AreUSerialz

    BUUCTF-[网鼎杯 2020 青龙组]AreUSerialz 看题 <?php include("flag.php"); highlight_file(__FILE__) ...

  10. Zookeeper:进大厂不得不学的分布式协同利器!

    大家好,我是冰河~~ 最近,有很多小伙伴让我更新一些Zookeeper的文章,正好也趁着清明假期把之前自己工作过程当中总结的Zookeeper知识点梳理了一番,打算写一个[精通Zookeeper系列] ...