【SHTSC2014】三叉神經樹

Description

計算神經學作爲新興的交叉學科近些年來一直是學術界的熱點。一種叫做SHOI 的神經組織因爲其和近日發現的化合物 SHTSC 的密切聯繫引起了人們的極大關注。
SHOI 組織由若干個 SHOI 細胞構成,SHOI 細胞之間形成嚴密的樹形結構。
每個 SHOI 細胞都有且只有一個輸出端,被稱爲軸突,除了一個特殊的、被稱爲根細胞的 SHOI 細胞的輸出作爲整個組織的輸出以外,其餘細胞的軸突均連向其上級 SHOI 細胞;並且有且只有三個接收端,被稱爲樹突,從其下級細胞或者其它神經組織那裏接收信息。SHOI 細胞的信號機制較爲簡單,僅有 0 和 1 兩種。每個 SHOI 細胞根據三個輸入端中 0 和 1 信號的多寡輸出較多的那一種。
現在給出了一段 SHOI 組織的信息,以及外部神經組織的輸入變化情況。請你模擬 SHOI 組織的輸出結果。

Input

第一行一個整數:n。表示 SHOI 組織的總細胞個數。SHOI 細胞由 1~n 編號,編號爲 1 的是根細胞。
從第二行開始的 n 行,每行三個整數 x1, x2, x3,分別表示編號爲 1~n 的 SHOI 細胞的樹突連接。1

Output

輸出 q 行每行一個整數,對應第 i 次外界輸入變化後的根細胞的輸出。

Sample Input

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

Sample Output

1
0
0
1
1

HINT

對於 100%的數據,n≤500000,q≤500000。

Solution

一道很巧妙的樹剖題目
維護(0,0,1)和(0,1,1)的一段連續的鏈
如果被修改就對這段鏈進行區間修改
查詢就單點查詢就好了
jzoj的棧特別小 特別噁心 所以要打個bfs版本的樹剖
有個地方忘記賦值爲0了
調了好久
代碼量很大 倦生

Code

#include <cstdio>
#include <cstring>
#include <algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fd(i,a,b) for(i=a;i>=b;i--)
#define L rt<<1
#define R (rt<<1)|1
using namespace std;
const int N=500005,ncov=-1;
int n,i,j,qq,dfn[N],seq[N],s[N],top[N],fa[N*3],v[N*3];
int a[N][4],q[N];
int read(){
    int sum=0;
    char c=getchar();
    while (c<'0'||c>'9') c=getchar();
    while (c>='0'&&c<='9'){
        sum=sum*10+c-'0';
        c=getchar();}
    return sum;
}
void bfs(){
    int l,r,x,i,res,j;
    l=0,r=1,q[1]=1;
    while (l<r){
        x=q[++l];
        fo(i,1,3) {
            j=a[x][i];
            if (j>n) continue;
            q[++r]=j;}
    }
    fo(i,1,n) s[i]=1,top[i]=i;
    dfn[1]=1,res=1;
    fd(i,n,1) {
        s[fa[q[i]]]+=s[q[i]];
        if (v[q[i]]>=2) v[fa[q[i]]]++;}
    s[0]=0;
    fo(i,1,n){
        x=q[i]; res=dfn[x]; int tmp=0;
        fo(j,1,3) if (a[x][j]<=n&&s[a[x][j]]>s[tmp]) tmp=a[x][j];
        if (tmp) top[tmp]=top[x],dfn[tmp]=res+1,res+=s[tmp];
        fo(j,1,3)
          if (a[x][j]<=n&&a[x][j]!=tmp) dfn[a[x][j]]=res+1,res+=s[a[x][j]];  
    }
    fo(i,1,n) seq[dfn[i]]=i;
}
struct Tseg{
    struct edge{
        int c,s,mx[2];
        void cov(int cc){
            mx[0]=mx[1]=0;
            c=cc; 
            if (c==1) mx[0]=s; if (c==2) mx[1]=s;
        }
    } tr[N<<3];
   void update(edge &rt,edge l,edge r){
     rt.s=l.s+r.s; 
     rt.mx[0]=r.mx[0],rt.mx[1]=r.mx[1];
     if (r.mx[0]==r.s) rt.mx[0]+=l.mx[0];
     if (r.mx[1]==r.s) rt.mx[1]+=l.mx[1]; 
   }
   void pushdown(int rt){
     if (tr[rt].c==ncov) return;
     tr[L].cov(tr[rt].c);
     tr[R].cov(tr[rt].c);
     tr[rt].c=ncov;
   }
   void build(int rt,int l,int r){
      tr[rt].c=ncov;
      if (l==r){
        tr[rt].s=1;
        tr[rt].cov(v[seq[l]]);
        return;}
        int mid=(l+r)>>1;
        build(L,l,mid),build(R,mid+1,r);
        update(tr[rt],tr[L],tr[R]);
   }
   void clear(){ build(1,1,n);}
   edge query(int rt,int l,int r,int x,int y){
      if (l==x&&r==y) return tr[rt];
      pushdown(rt);
      int mid=(l+r)>>1;
      if (y<=mid) return query(L,l,mid,x,y);
        else if (x>mid) return query(R,mid+1,r,x,y);
      edge res;
      update(res,query(L,l,mid,x,mid),query(R,mid+1,r,mid+1,y));
      return res;
   }
   int search(int rt,int l,int r,int x){
      if (l==r) return tr[rt].c;
      pushdown(rt);
      int mid=(l+r)>>1;
      if (x<=mid) return search(L,l,mid,x);
        else return search(R,mid+1,r,x);
   }
   void change(int rt,int l,int r,int x,int y,int c){
      if (l==x&&r==y) {
          tr[rt].cov(c);
          return;}
      pushdown(rt);
      int mid=(l+r)>>1;
      if (y<=mid) change(L,l,mid,x,y,c);
        else if (x>mid) change(R,mid+1,r,x,y,c);
          else change(L,l,mid,x,mid,c),change(R,mid+1,r,mid+1,y,c);
      update(tr[rt],tr[L],tr[R]);
   } 
   void deal(int x,int p,int c){
      for(;top[x]!=top[p];x=fa[top[x]]) change(1,1,n,dfn[top[x]],dfn[x],c);
      change(1,1,n,dfn[p],dfn[x],c);
   }
   int modify(int x){
      int key=v[x];v[x]^=1;
      int tmp=fa[x];
      while (1){
        edge res=query(1,1,n,dfn[top[tmp]],dfn[tmp]);
        if (res.s!=res.mx[key]) break;
        tmp=top[tmp];
        if (!fa[tmp]) break;
        if (search(1,1,n,dfn[fa[tmp]])!=key+1) break;
        tmp=fa[tmp];}
     int p=search(1,1,n,dfn[tmp]);
     if (p!=key+1){
          change(1,1,n,dfn[tmp],dfn[tmp],p+(key?-1:1));
          return search(1,1,n,1)>=2;}
       if (tmp==top[tmp]) p=tmp;
        else p=seq[dfn[tmp]-query(1,1,n,dfn[top[tmp]],dfn[tmp]).mx[key]+1];
       deal(fa[x],p,v[x]+1);
       if (fa[p]) change(1,1,n,dfn[fa[p]],dfn[fa[p]],search(1,1,n,dfn[fa[p]])+(key?-1:1));
       return search(1,1,n,1)>=2;
   }    
} seg;
void work(){
    seg.clear();
    qq=read();
    while (qq){
        qq--;
        i=read();
            printf("%d\n",seg.modify(i));
    }
}
int main(){
    freopen("neuron.in","r",stdin);
    freopen("neuron.out","w",stdout);
    n=read();
    fo(i,1,n)
      fo(j,1,3){
        a[i][j]=read();
        fa[a[i][j]]=i;}
    fo(i,n+1,3*n+1) v[i]=read(),v[fa[i]]+=v[i];
    bfs();
    work();
}
發佈了58 篇原創文章 · 獲贊 1 · 訪問量 6150
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章