列表

详情


NC20590. [SHOI2014]三叉神经树

描述

计算神经学作为新兴的交叉学科近些年来一直是学术界的热点。一种叫做SHOI 的神经组织因为其和近日发现的化合物 SHTSC 的密切联系引起了人们的极大关注。 SHOI 组织由若干个 SHOI 细胞构成,SHOI 细胞之间形成严密的树形结构。 每个 SHOI 细胞都有且只有一个输出端,被称为轴突,除了一个特殊的、被称为根细胞的 SHOI 细胞的输出作为整个组织的输出以外,其余细胞的轴突均连向其上级 SHOI 细胞;并且有且只有三个接收端,被称为树突,从其下级细胞或者其它神经组织那里接收信息。SHOI 细胞的信号机制较为简单,仅有 0 和 1 两种。每个 SHOI 细胞根据三个输入端中 0 和 1 信号的多寡输出较多的那一种。 现在给出了一段 SHOI 组织的信息,以及外部神经组织的输入变化情况。请你模拟 SHOI 组织的输出结果。

输入描述

第一行一个整数:n。表示 SHOI 组织的总细胞个数。SHOI 细胞由 1~n 编号,编号为 1 的是根细胞。 
从第二行开始的 n 行,每行三个整数 x1, x2, x3,分别表示编号为 1~n 的 SHOI 细胞的树突连接。1 < xi ≤ n 表示连向编号为 xi 的细胞的轴突, n < xi ≤ 3n+1 表示连向编号为 xi 的外界输入。输入数据保证给出的 SHOI 组织是合法的且所有的 xi 两两不同。
接下来一行 2n+1 个 0/1 的整数,表示初始时的外界输入。 
第 n+3 行有一个整数:q,表示总操作数。 
之后 q 行每行一个整数 x,表示编号为 x 的外界输入发生了变化。

输出描述

输出 q 行每行一个整数,对应第 i 次外界输入变化后的根细胞的输出。

示例1

输入:

3 
2 3 4 
5 6 7 
8 9 10 
0 0 0 0 1 1 1 
5 
4 
4 
5 
6 
8

输出:

1
0
0
1
1

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++11(clang++ 3.9) 解法, 执行用时: 462ms, 内存消耗: 50352K, 提交时间: 2020-03-31 10:58:42

#include<cstdio>
#include<algorithm>
#define RG register
#define I inline
#define R RG int
#define lc c[x][0]
#define rc c[x][1]
#define G if(++ip==ie)if(fread(ip=ibuf,1,L,stdin))
using namespace std;
const int N=5e5+9,M=1.5e6+9,L=1<<19;
char ibuf[L],*ie=ibuf+L,*ip=ie-1;
int n,f[M],c[N][2],t[N],n1[N],n2[N],v[M],q[M],d[N];
I int max(R x,R y){return x>y?x:y;}
I int in(){
    G;while(*ip<'-')G;
    R x=*ip&15;G;
    while(*ip>'-'){(x*=10)+=*ip&15;G;}
    return x;
}
I bool nrt(R x){
    return c[f[x]][0]==x||c[f[x]][1]==x;
}
I void up(R x){//先右儿子再自己最后左儿子
    if(!(n1[x]=n1[rc])&&!(n1[x]=x*(v[x]!=1)))n1[x]=n1[lc];
    if(!(n2[x]=n2[rc])&&!(n2[x]=x*(v[x]!=2)))n2[x]=n2[lc];
}
I void dn(R x,R tg){//被区间修改的要么都是1要么都是2,直接反转信息
    v[x]^=3;swap(n1[x],n2[x]);t[x]+=tg;
}
I void all(R x){
    if(nrt(x))all(f[x]);
    if(t[x])dn(lc,t[x]),dn(rc,t[x]),t[x]=0;
}
I void rot(R x){
    R y=f[x],z=f[y],k=c[y][1]==x,w=c[x][!k];
    if(nrt(y))c[z][c[z][1]==y]=x;
    f[f[f[c[c[x][!k]=y][k]=w]=y]=x]=z;up(y);
}
I void sp(R x){
    all(x);
    for(R y;nrt(x);rot(x))
        if(nrt(y=f[x]))rot((c[f[y]][0]==y)^(c[y][0]==x)?x:y);
    up(x);
}
I void ac(R x){
    for(R y=0;x;sp(x),rc=y,up(y=x),x=f[x]);
}
int main(){
    n=in();R he,tl=0,i,x,tp,nowrt;//nowrt全局记录根的输出,方便,减小常数
    for(i=1;i<=n;++i)d[f[in()]=f[in()]=f[in()]=i]=3;
    for(;i<=3*n+1;++i)v[q[++tl]=i]=in()<<1;
    for(he=1;he<=tl;++he){//懒得dfs了,直接从下往上拓扑排序预处理
        x=q[he];if(x<=n)up(x);
        v[f[x]]+=v[x]>>1;
        if(!--d[f[x]])q[++tl]=f[x];
    }
    nowrt=v[1]>>1;
    for(R q=in();q;--q){
        tp=(v[x=in()]^=2)-1;//记录当前变化类型
        ac(x=f[x]);sp(x);
        if((~tp?n1:n2)[x]){
            sp(x=(~tp?n1:n2)[x]);
            dn(rc,tp),up(rc);
            v[x]+=tp;up(x);
        }
        else dn(x,tp),up(x),nowrt^=1;//注意特判
        putchar(nowrt|'0');putchar('\n');
    }
    return 0;
}

上一题