[データ構造] --SHOI2014三叉ツリー

質問を書き込むための最初の黒、とても神経質(武士)


 

(写真は、ロス・バレーからカット)

  この質問は、私たちが葉ノードの値を変更した場合練習の手の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 }

 

 

 

  

 

おすすめ

転載: www.cnblogs.com/Nelson992770019/p/11333198.html