• [SHOI2014]三叉神经树


    Description:

    计算神经学作为新兴的交叉学科近些年来一直是学术界的热点。一种叫做SHOI 的神经组织因为其和近日发现的化合物 SHTSC 的密切联系引起了人们的极大关注。

    SHOI 组织由若干个 SHOI 细胞构成,SHOI 细胞之间形成严密的树形结构。每个 SHOI 细胞都有且只有一个输出端,被称为轴突,除了一个特殊的、被称为根细胞的 SHOI 细胞的输出作为整个组织的输出以外,其余细胞的轴突均连向其上级 SHOI 细胞;并且有且只有三个接收端,被称为树突,从其下级细胞或者其它神经组织那里接收信息。SHOI 细胞的信号机制较为简单,仅有 0和 1两种。每个 SHOI 细胞根据三个输入端中 0和 1信号的多寡输出较多的那一种。

    现在给出了一段 SHOI 组织的信息,以及外部神经组织的输入变化情况。请你模拟 SHOI 组织的输出结果。

    Description:

    输入的第一行包含一个整数 n。表示 SHOI 组织的总细胞个数。SHOI 细胞由 1~ n 编号,编号为 1 的是根细胞。

    从第二行开始的 n行,每行三个整数 (x_1, x_2, x_3)
    ​ ,分别表示编号为 1~ n 的 SHOI 细胞的树突连接。$1 < x_i leq ≤n ( 表示连向编号为) x_i$
    ​ 的细胞的轴突, n < x_i leq 3n+1
    ​ ≤3n+1 表示连向编号为 x_i
    ​ 的外界输入。输入数据保证给出的 SHOI 组织是合法的,且所有的 x_i
    ​ 两两不同。

    接下来一行包含 2n+1 个 0/1的整数,表示初始时的外界输入。

    第 n+3行有一个整数 q,表示总操作数。

    之后 q 行每行一个整数 x,表示编号为 x 的外界输入发生了变化。

    Solution:

    很神仙的一道题,思路秒出,但是细节真的很多,很久才想清楚
    首先考虑每次修改只会改变状态为1/2的点
    考虑用LCT维护#splay#的点子树中有没有不为1/2的点
    举个例子,现在把一个叶节点从0修改成1
    每次拉出一条链后把叶节点旋到根,并找到#原树中深度最大#且不为1的点
    显然从叶节点到这个点的所有的点的状态都要+1,而对其他点没有影响
    于是打个标记就行了,1修改成0同理

    至于询问,直接输出状态就行
    代码还是有很多细节的

    #include<bits/stdc++.h>
    using namespace std;
    const int mxn=2e6+5;
    int n,q,s;
    int a[mxn],son[mxn][3],st[mxn], val[mxn], tag[mxn], fa[mxn],f[mxn],no1[mxn], no2[mxn];
    
    inline void chkmax(int &x,int y) {if(x<y) x=y;}
    inline void chkmin(int &x,int y) {if(x>y) x=y;}
    
    namespace lct {
        int ch[mxn][2];
        int isnotrt(int x) {
            return ch[fa[x]][0]==x||ch[fa[x]][1]==x;
        }
        void update(int x,int z) {
            val[x]+=z; tag[x]+=z;
            if(z>0) no2[x]=no1[x],no1[x]=0; 
            else no1[x]=no2[x],no2[x]=0; //很方便的继承,考虑这样为什么不会错,因为这条路径上不是1就是2
        }
        void push_up(int x) {
            no1[x]=no1[ch[x][0]]|no1[ch[x][1]]|(val[x]!=1);
            no2[x]=no2[ch[x][0]]|no2[ch[x][1]]|(val[x]!=2);
        }
        void push_down(int x) {
            if(tag[x]) {
                if(ch[x][0]) update(ch[x][0],tag[x]);
                if(ch[x][1]) update(ch[x][1],tag[x]);
                tag[x]=0;
            }
        }
        void rotate(int x) {
            int y=fa[x],z=fa[y],tp=ch[y][1]==x;
            if(isnotrt(y)) ch[z][ch[z][1]==y]=x; fa[x]=z;
            ch[y][tp]=ch[x][tp^1]; fa[ch[x][tp^1]]=y;
            ch[x][tp^1]=y; fa[y]=x;
            push_up(y); push_up(x);
        }
        void splay(int x) {
            int u=x; s=0; st[++s]=x;
            while(isnotrt(u)) st[++s]=u=fa[u];
            while(s) push_down(st[s]),--s;
            while(isnotrt(x)) {
                int y=fa[x],z=fa[y];
                if(isnotrt(y))
                    (ch[y][1]==x)^(ch[z][1]==y)?rotate(x):rotate(y);
                rotate(x);
            }
        }
        void access(int x) {
            for(int y=0;x;x=fa[y=x]) 
                splay(x),ch[x][1]=y,push_up(x);
        }
        int find1(int x) {
            push_down(x);
            if(!no1[x]) return 0;
            if(no1[ch[x][1]]) return find1(ch[x][1]);
            if(val[x]!=1) return x; //找点
            return find1(ch[x][0]);
        }
        int find2(int x) {
            push_down(x);
            if(!no2[x]) return 0;
            if(no2[ch[x][1]]) return find2(ch[x][1]); 
            if(val[x]!=2) return x;
            return find2(ch[x][0]);
        }
    }
    using namespace lct;
    
    void dfs(int u)
    {
        if(u>n) return ;
        for(int i=0;i<3;++i) {
            dfs(son[u][i]);
            val[u]+=(val[son[u][i]]>1); //赋初值
        }
    }
    
    int main()
    {
        scanf("%d",&n); int x;
        for(int i=1;i<=n;++i) {
            for(int j=0;j<3;++j) {
                scanf("%d",&son[i][j]);
                fa[son[i][j]]=f[son[i][j]]=i;
            }
        }
        for(int i=1;i<=2*n+1;++i)
            scanf("%d",&val[n+i]),++val[n+i]; 
        dfs(1); scanf("%d",&q);
        for(int i=1;i<=q;++i) {
            scanf("%d",&x); int pos;
            access(x); splay(x);
            if(val[x]>1) {
                pos=find2(ch[x][0]); access(f[pos]);
                splay(x); update(x,-1);
            }
            else {
                pos=find1(ch[x][0]); access(f[pos]);
                splay(x); update(x,1); 
            }
            splay(1);
            printf("%d
    ",val[1]>1);
        }
        return 0;
    }
    
  • 相关阅读:
    PHP Laravel Install and Quickstart
    PHP Composer
    PHP学习 Cookie和Session
    PHP学习 Object Oriented 面向对象 OO
    PHP学习 例外和错误处理
    PHP学习 文件访问和写入
    PHP学习 函数 function
    PHP学习 流程控制和数组
    修改docker镜像地址为阿里云
    通信对象 System.ServiceModel.Channels.ServiceChannel 无法用于通信,因为其处于“出错”状态
  • 原文地址:https://www.cnblogs.com/list1/p/10453701.html
Copyright © 2020-2023  润新知