NC20590. [SHOI2014]三叉神经树
描述
输入描述
第一行一个整数: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; }