質問を書き込むための最初の黒、とても神経質(武士)
この質問は、私たちが葉ノードの値を変更した場合練習の手のLCTのタイトル、木に与えられた最初のタイトルを、であると言うことができ、その親の範囲親ノードが変更された場合、そのノードもよい祖父変更の連鎖のために存在するかどうか、それは変化しますので、我々は推測しますか?
ノードは0/1/2/3た状態を表す場合、明らかに、即ち、息子は桁数を含み、次いで、浅いから深い1/0/1/1/0までの期間に、ノード0が最も深いとなります1のために、シーケンスになるだろう:1/1/2/2/1、浅いは、そのノード0にまで影響を与えます。
あなたのアカウントに実際には1から0に変更を取る場合は、(連鎖が2さ)したがって、我々はの出現まで1/2、1/2連続していないが含まれている満たすためにいくつかのボトムアップの範囲を維持することを検討した理由であり、ポイントは、その後、間隔を変更して、単独のポイントを変更するには、メンテナンスが完了です。
具体的には、のは、点xに件名を開くパスを開き、その後、1月2日ではありません最も深いノードを探して、いくつかのヒントを変更してみましょう:
1. 2つのリーフノードを乗じ、2つのリーフノードで割った和に等しい分岐は、非常に便利であることができます。
上向きのステップ2.更新:そう右の深さのスプレイメンテナンス、ので - >自分で - >左の順序は、最高の判断でした。
3.ステップダウン送信:配列NUM1 xを維持交換しながら、各区間の本質は、3の排他的論理和の値、1~1 2,2なり、NUM2(この期間1ため配列2に等しい一部を維持しながら、2配列はすべて、変更されます)
4.多くの場合、ノートカード、インラインレジスタint型ああああ、迅速なものを読むストレート4.2sから200msの時間まで、開かれています。
5.私は悲惨なピットメモリだった、すべてが大きなポイントを開くために、できるだけ多くの対象者の要件に応じて、アレイの開口サイズの後、TLEを変え、数回それを開いていたもの、通常のサイズWA、RE、MLEの様々な開きます。
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define rs c[x][1] 4 #define ls c[x][0] 5 const int N=2e6+5; 6 int n; 7 int f[N],cnt,sum[N],q,tot,head[N],aa,bb,cc,ans; 8 int c[N][2],st[N],num2[N],num1[N],tag[N]; 9 inline int read() 10 { 11 int ans = 0,op = 1;char ch = getchar(); 12 while(ch < '0' || ch > '9') {if(ch == '-') op = -1;ch = getchar();} 13 while(ch >='0' && ch <= '9') ans = ans * 10 + ch - '0',ch = getchar(); 14 return ans * op; 15 } 16 struct edge{ 17 int next,to; 18 }e[N<<1]; 19 void addedge(int from,int to){ 20 e[++cnt].to=to; 21 e[cnt].next=head[from]; 22 head[from]=cnt; 23 } 24 void dfs(int u){ 25 for(int i=head[u];i;i=e[i].next){ 26 dfs(e[i].to); 27 sum[u]+=(sum[e[i].to]>>1); 28 } 29 } 30 int nroot(int x){ 31 return c[f[x]][0]==x||c[f[x]][1]==x; 32 } 33 void pushup(int x){ 34 num1[x]=num1[rs]; 35 if(!num1[x]&&sum[x]!=1) num1[x]=x; 36 if(!num1[x]) num1[x]=num1[ls]; 37 num2[x]=num2[rs]; 38 if(!num2[x]&&sum[x]!=2) num2[x]=x; 39 if(!num2[x]) num2[x]=num2[ls]; 40 } 41 void pusm(int x,int d){ 42 sum[x]^=3; 43 swap(num1[x],num2[x]); 44 tag[x]+=d; 45 } 46 void pushdown(int x){ 47 if(nroot(x)) pushdown(f[x]); 48 if(tag[x]){ 49 pusm(ls,tag[x]); 50 pusm(rs,tag[x]); 51 tag[x]=0; 52 } 53 } 54 void rotate(int x){ 55 int y=f[x],z=f[y],k=c[y][1]==x,w=c[x][k^1]; 56 if(nroot(y)) c[z][c[z][1]==y]=x; 57 c[x][k^1]=y; 58 c[y][k]=w; 59 if(w) f[w]=y; 60 f[y]=x; 61 f[x]=z; 62 pushup(y); 63 64 } 65 void splay(int x){ 66 pushdown(x); 67 int y=x,z=0; 68 st[++z]=y; 69 while(nroot(y)) st[++z]=y=f[y]; 70 while(z) pushdown(st[z--]); 71 while(nroot(x)){ 72 y=f[x],z=f[y]; 73 if(nroot(y)) rotate((c[y][0]==x)^(c[z][0]==y)?x:y); 74 rotate(x); 75 } 76 pushup(x); 77 } 78 void access(int x){ 79 for(int g=0;x;x=f[g=x]){ 80 splay(x); 81 rs=g; 82 pushup(x); 83 } 84 } 85 int main(){ 86 // freopen("neuron.in","r",stdin); 87 // freopen("neuron.out","w",stdout); 88 n=read(); 89 int i; 90 for(i=1;i<=n;i++){ 91 aa=read(),bb=read(),cc=read(); 92 f[aa]=f[bb]=f[cc]=i; 93 addedge(i,aa); 94 addedge(i,bb); 95 addedge(i,cc); 96 } 97 for(;i<=3*n+1;i++){ 98 aa=read(); 99 sum[i]=(aa<<1); 100 } 101 dfs(1); 102 q=read(); 103 ans=sum[1]>>1; 104 for(i=1;i<=q;i++){ 105 aa=read(); 106 sum[aa]^=2;//单点修改 107 int k=sum[aa]-1; 108 aa=f[aa]; 109 access(aa); 110 splay(aa);//将区间的端点旋转到根 111 int p=(~k)?num1[aa]:num2[aa];//找到最深的非1或2点 112 if(!p) pusm(aa,k),pushup(aa),ans^=1;//如果这个点不存在,说明就是原树根了 113 else{ 114 splay(p);//这个时候aa点已经在p的右子树了 115 pusm(c[p][1],k); 116 pushup(c[p][1]); 117 sum[p]+=k; 118 pushup(p); 119 } 120 printf("%d\n",ans); 121 } 122 return 0; 123 }