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();
}