洛谷4322 SHOI2014 三叉神经树(LCT+思维)
好久之前做的题了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+思维)的更多相关文章
- 洛谷P4332 [SHOI2014]三叉神经树(LCT,树剖,二分查找,拓扑排序)
洛谷题目传送门 你谷无题解于是来补一发 随便百度题解,发现了不少诸如树剖\(log^3\)LCT\(log^2\)的可怕描述...... 于是来想想怎么利用题目的性质,把复杂度降下来. 首先,每个点的 ...
- 洛谷P4332 [SHOI2014]三叉神经树(LCT)
传送门 FlashHu大佬太强啦%%% 首先,我们可以根据每一个点的权值为$1$的儿子的个数把每个点记为$0~3$,表示这一个点的点权 先考虑一下暴力的过程,假设从$0$变为$1$,先更改一个叶子结点 ...
- P4332 [SHOI2014]三叉神经树(LCT)
Luogu4332 LOJ2187 题解 代码-Tea 题意 : 每个点有三个儿子 , 给定叶节点的权值\(0\)或\(1\)且支持修改 , 非叶子节点的权值为当有\(>=2\)个儿子的权值为\ ...
- 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\) 刚刚发布了引领世界潮流的下一代电子产品-- 概率充电器: "采用全新纳米 ...
- 洛谷AT2342 Train Service Planning(思维,动态规划,珂朵莉树)
洛谷题目传送门 神仙思维题还是要写点东西才好. 建立数学模型 这种很抽象的东西没有式子描述一下显然是下不了手的. 因为任何位置都以\(k\)为周期,所以我们只用关心一个周期,也就是以下数都在膜\(k\ ...
随机推荐
- java js转码解码
摘自网友:https://blog.csdn.net/sgear/article/details/1509400?utm_medium=distribute.pc_relevant.none-task ...
- java发送短信开发,第三方接口方法
必备的三个jar包Maven有自己去下: commons-logging commons-logging 1.1 commons-httpclient commons-httpclient 3.1 c ...
- ES6——简单的多态
简单的多态 多态: 1.同一个接口,在不同情况下做不一样的事情:相同的接口,不同的表现: 2.接口本身只是一组定义,实现都是子类里面:需要子类去实现的方法(子类只需重写与父类同名的方法,即可达到覆盖的 ...
- FeignClient注解属性configuration不生效问题排查思路
FeignClient注解属性configuration不生效问题排查思路 问题背景 我们知道,"如果需要自定义单个Feign配置,Feign的@Configuration 注解的类不能与@ ...
- BUUCTF-[CISCN2019 华东北赛区]Web2
BUUCTF-[CISCN2019 华东北赛区]Web2 看题 一个论坛,内容不错:) 可以投稿,点击投稿发现要注册,那就先注册登录.随便账号密码就行. 常规操作,扫一下站点,发现有admin.php ...
- Django的form组件基本使用——生成标签
from django.contrib import admin from django.urls import path from app01 import views urlpatterns = ...
- Intel® QAT加速卡之同步异步模式
QAT 的两种操作模式 Intel QAT API同时支持同步和异步两种操作模式. 为了获得最佳性能,该应用程序应能够向加速引擎提交多个未完成的请求. 提交多个未完成的请求可最大程度地减少加速引擎上的 ...
- 跨 Docker 宿主机 macvlan 类型
跨 Docker 宿主机 macvlan 类型 前言 a. 本文主要为 Docker的视频教程 笔记. b. 环境为 三台 CentOS 7.0 虚拟机 (Vmware Workstation 15 ...
- Docker修改容器中的时间
Docker修改容器中的时间 前言 在公司开发时使用 Docker 创建数据库(SQL Server)的实例十分方便,还原数据库也只要设置好共享文件夹,在 SQL Server Management ...
- 通过Wireshark抓包分析谈谈DNS域名解析的那些事儿
文/朱季谦 本文主要想通过动手实际分析一下是如何通过DNS服务器来解析域名获取对应IP地址的,毕竟,纸上得来终觉浅,绝知此事要躬行. 域名与IP地址 当在浏览器上敲下"www.baidu.c ...