3553: [Shoi2014]三叉神经树(树链剖分)
这道题特别恶心,首先我们可以发现更改的就是出现连续的一或二,那么就用线段树+树链剖分找到这个范围
想到是不难想,就是打起来恶心罢了= =
CODE:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<stack>
using namespace std;
#define maxn 500100
struct edges{
int to,next;
}edge[maxn*3];
int l,next[maxn];
int addedge(int x,int y) {
edge[++l]=(edges){y,next[x]};next[x]=l;
}
int s[maxn],ch[maxn],fa[maxn*3],ans[maxn*3],q[maxn];
int bfs() {
int r=0;
q[++r]=1;
int l=0;
while (l<r) {
int u=q[++l];s[u]=1;
for (int i=next[u];i;i=edge[i].next) {
fa[edge[i].to]=u;q[++r]=edge[i].to;
}
}
for (int i=r;i;i--) {
s[fa[q[i]]]+=s[q[i]];
ch[fa[q[i]]]=s[ch[fa[q[i]]]]<s[q[i]]?q[i]:ch[fa[q[i]]];
ans[fa[q[i]]]+=ans[q[i]]>1?1:0;
}
}
int add[maxn],pos[maxn],pre[maxn];
int cnt;
bool b[maxn];
int heavy(int x,bool y) {
stack<int > s;
s.push(1);
add[pos[++cnt]=1]=cnt;
pre[1]=1;
while (!s.empty()) {
int x=s.top();s.pop();
if (!b[x]&&ch[x]) {
s.push(x);
s.push(ch[x]);
add[pos[++cnt]=ch[x]]=cnt;
pre[ch[x]]=pre[x];
b[x]=1;
continue;
}
for (int i=next[x];i;i=edge[i].next) {
if (edge[i].to!=ch[x]) {
s.push(x);
s.push(edge[i].to);
add[pos[++cnt]=edge[i].to]=cnt;
pre[edge[i].to]=edge[i].to;
next[x]=edge[i].next;
break;
}
}
}
return 0;
}
struct bo {
int sz,s,len;
};
struct node{
int l,r,lz;bo b;
}t[maxn*8];
#define s(x) t[x].b.s
#define sz(x) t[x].b.sz
#define len(x) t[x].b.len
bo update(bo l,bo r) {
bo ans;
ans.sz=l.sz+r.sz;
ans.s=r.s;
ans.len=r.len;
if (l.s==r.s&&r.len==r.sz) ans.len+=l.len;
return ans;
}
#define lc(x) (x<<1)
#define rc(x) ((x<<1)+1)
#define mid ((r+l)>>1)
#define upd(x) t[x].b=update(t[lc(x)].b,t[rc(x)].b)
void build(int x,int l,int r) {
t[x].l=l;t[x].r=r;
sz(x)=r-l+1;
if (l==r) {s(x)=ans[pos[l]];len(x)=1;return ;}
build(lc(x),l,mid);build(rc(x),mid+1,r);
upd(x);
}
#define lz(x) t[x].lz
void pushback(int x) {
if (t[x].lz==0) return;
int l=lc(x),r=rc(x);
lz(l)+=lz(x);lz(r)+=lz(x);
s(l)+=lz(x);s(r)+=lz(x);
lz(x)=0;
}
bo que(int x,int y) {
int l=t[x].l,r=t[x].r;
if (r<=y) return t[x].b;
pushback(x);
if (y<=mid) return que(lc(x),y);
if (y>mid) return update(que(lc(x),y),que(rc(x),y));
}
void inc(int x,int x1,int y1,int z) {
int l=t[x].l,r=t[x].r;
if (y1<l||x1>r) return ;
if (x1<=l&&r<=y1) {
t[x].lz+=z;
s(x)+=z;
return ;
}
pushback(x);
inc(lc(x),x1,y1,z);inc(rc(x),x1,y1,z);
upd(x);
}
void gen(int x,int flag) {
while (x) {
bo tmp=que(1,add[x]);
switch (flag) {
case 0:
if (tmp.s==2) {
if (tmp.len>=add[x]-add[pre[x]]+1) {
inc(1,add[pre[x]],add[x],-1);
x=fa[pre[x]];
} else {
inc(1,add[x]-tmp.len,add[x],-1);
x=0;
}
}else {
inc(1,add[x],add[x],-1);
x=0;
}
break;
case 1:
if (tmp.s==1) {
if (tmp.len>=add[x]-add[pre[x]]+1) {
inc(1,add[pre[x]],add[x],1);
x=fa[pre[x]];
} else {
inc(1,add[x]-tmp.len,add[x],1);
x=0;
}
}else {
inc(1,add[x],add[x],1);
x=0;
}
break;
}
}
return ;
}
int main(){
int n;
scanf("%d",&n);
for (int i=1;i<=n;i++) {
int x1,x2,x3;
scanf("%d%d%d",&x1,&x2,&x3);
if (x1<=n) addedge(i,x1);else fa[x1]=i;
if (x2<=n) addedge(i,x2);else fa[x2]=i;
if (x3<=n) addedge(i,x3);else fa[x3]=i;
}
for (int i=1;i<=2*n+1;i++) {
scanf("%d",&ans[i+n]);
ans[fa[i+n]]+=ans[i+n];
}bfs();
heavy(1,1);
build(1,1,n);
int Q;
scanf("%d",&Q);
while (Q--) {
int x;
scanf("%d",&x);
ans[x]^=1;
gen(fa[x],ans[x]);
printf("%d\n",que(1,1).s>=2?1:0);
}
return 0;
}
3553: [Shoi2014]三叉神经树(树链剖分)的更多相关文章
- [BZOJ 3553][SHOI2014]三叉神经树
传送门(下面也有题面) 题目大意: 一颗有根树,每个非叶子节点都有三个子节点,每个节点的权为0/1. 每个节点的权 取决于其所有子节点中 哪种权出现的次数更多. 有若干次询问,每次询问修改一个叶子节点 ...
- 线段树&数链剖分
傻逼线段树,傻逼数剖 线段树 定义: 线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点. 使用线段树可以快速的查找某一个节点在若干条线段中出现 ...
- BZOJ 3553: [Shoi2014]三叉神经树 LCT
犯傻了,想到了如果是 0->1 的话就找最深的非 1 编号,是 1 -> 0 的话就找最深的非 0 编号. 但是没有想到这个东西可以直接维护. 假设不考虑叶子节点,那么如果当前点的值是 1 ...
- 【BZOJ-3553】三叉神经树 树链剖分
3553: [Shoi2014]三叉神经树 Time Limit: 160 Sec Memory Limit: 256 MBSubmit: 347 Solved: 112[Submit][Stat ...
- [LOJ3014][JOI 2019 Final]独特的城市——树的直径+长链剖分
题目链接: [JOI 2019 Final]独特的城市 对于每个点,它的答案最大就是与它距离最远的点的距离. 而如果与它距离为$x$的点有大于等于两个,那么与它距离小于等于$x$的点都不会被计入答案. ...
- UOJ#30/Codeforces 487E Tourists 点双连通分量,Tarjan,圆方树,树链剖分,线段树
原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ30.html 题目传送门 - UOJ#30 题意 uoj写的很简洁.清晰,这里就不抄一遍了. 题解 首先建 ...
- BZOJ1758[Wc2010]重建计划——分数规划+长链剖分+线段树+二分答案+树形DP
题目描述 输入 第一行包含一个正整数N,表示X国的城市个数. 第二行包含两个正整数L和U,表示政策要求的第一期重建方案中修建道路数的上下限 接下来的N-1行描述重建小组的原有方案,每行三个正整数Ai, ...
- CF487E Tourists 圆方树、树链剖分
传送门 注意到我们需要求的是两点之间所有简单路径中最小值的最小值,那么对于一个点双联通分量来说,如果要经过它,则一定会经过这个点双联通分量里权值最小的点 注意:这里不能缩边双联通分量,样例\(2\)就 ...
- 2019.01.08 codeforces 1009F. Dominant Indices(长链剖分)
传送门 长链剖分模板题. 题意:给出一棵树,设fi,jf_{i,j}fi,j表示iii的子树中距离点iii距离为jjj的点的个数,现在对于每个点iii要求出使得fif_ifi取得最大值的那个jjj ...
随机推荐
- leetcode-004 insertion sort list
package leetcode; class ListNode { int val; ListNode next; ListNode(int x) { val = x; next = null; } ...
- CSS十问
CSS十问——好奇心+刨根问底=CSSer 最近有时间,想把酝酿的几篇博客都写出来,今天前端小学生带着10个问题,跟大家分享一下学习CSS的一些体会,我觉得想学好CSS,必须保持一颗好奇心和刨根问 ...
- spring.net的基本搭建
这几天在学C#,感觉还是需要一个控制反转的框架,正好Spirng也有.net版的,看着API搭建一个 大致目录是这样的,我们在APP.CONFIG里面配好xml文件的地址,这个APP.CONFIG就相 ...
- 按住ctrl键可以在新窗口打开图片
用firebug查看网页时,img标签(或background属性里面的url地址源)里面的图片源按住ctrl键可以弹出新窗口显示,并可右键另存为到本地目录
- Mysql中常用的函数汇总
Mysql中常用的函数汇总: 一.数学函数abs(x) 返回x的绝对值bin(x) 返回x的二进制(oct返回八进制,hex返回十六进制)ceiling(x) 返回大于x的最小整数值exp(x) 返回 ...
- js变量作用域及访问权限的探讨(2)
每一种语言都有变量的概念,变量是用来存储信息的一个元素.比如下面这个函数: 复制代码 代码如下: function Student(name,age,from) { this.name = n ...
- Mac 安装Rudy环境 pod安装前的准备工作
之前已经说过怎么使用pod 今天说一下安装pod之前的准备工作 首先呢就是Rudy 环境(前提是你已经安装了Xcode) 在终端输入一下命令 期间可能也许会要你输入密码 curl -L https:/ ...
- 安装Pomelo
安装pomelo的过程中会使用到C++编译器. 请确保你的Windows系统满足以下两个条件: python(2.5<version<3.0). VC++ 编译器,包含在Visual St ...
- enum 用法
public enum WeekDay { SUN(, "Sunday", "SUN"), MON(, "Monday", "MO ...
- Cookie的一些用法
Cookie的一些用法: package com.stono.servlet.listenerorder; import java.io.IOException; import java.io.Pri ...