1. 程式人生 > >洛谷 P1501 [國家集訓隊]Tree II

洛谷 P1501 [國家集訓隊]Tree II

Go 不能 連續 esp 返回 while struct event 相同

看來這個LCT板子並沒有什麽問題

  1 #include<cstdio>
  2 #include<algorithm>
  3 using namespace std;
  4 typedef long long LL;
  5 const LL md=51061;
  6 namespace LCT
  7 {
  8 struct Node
  9 {
 10     Node *ch[2],*fa;
 11     bool rev;
 12     LL addv,mulv;
 13     LL dat,sum,sz;
 14     void
padd(LL x) 15 { 16 addv=(addv+x)%md;dat=(dat+x)%md;sum=(sum+x*sz)%md; 17 } 18 void pmul(LL x) 19 { 20 addv=addv*x%md;mulv=mulv*x%md;dat=dat*x%md;sum=sum*x%md; 21 } 22 void upd() 23 { 24 sum=((ch[0]?ch[0]->sum:0)+(ch[1]?ch[1]->sum:0
)+dat)%md; 25 sz=(ch[0]?ch[0]->sz:0)+(ch[1]?ch[1]->sz:0)+1; 26 } 27 void pd() 28 { 29 if(rev) 30 { 31 swap(ch[0],ch[1]); 32 if(ch[0]) ch[0]->rev^=1; 33 if(ch[1]) ch[1]->rev^=1; 34 rev=0;
35 } 36 if(mulv!=1) 37 { 38 if(ch[0]) ch[0]->pmul(mulv); 39 if(ch[1]) ch[1]->pmul(mulv); 40 mulv=1; 41 } 42 if(addv) 43 { 44 if(ch[0]) ch[0]->padd(addv); 45 if(ch[1]) ch[1]->padd(addv); 46 addv=0; 47 } 48 } 49 }nodes[300100]; 50 LL mem; 51 Node *getnode() 52 { 53 return nodes+(mem++); 54 } 55 bool isroot(Node *x) 56 { 57 return (!x->fa)||((x->fa->ch[0]!=x)&&(x->fa->ch[1]!=x)); 58 } 59 bool gson(Node *o) {return o==o->fa->ch[1];}//獲得是父親的左兒子(返回0)還是右兒子(1),要求保證存在父親 60 void rotate(Node *o,bool d) 61 //在o子樹中執行d=0左旋,d=1右旋,在旋轉前不標記下傳,並將o父節點的對應子節點由o變為需要值,要求保證存在子樹(!d) 62 { 63 Node *k=o->ch[!d];if(!isroot(o)) o->fa->ch[gson(o)]=k;//註意這一句修改o父節點的要寫在前面,曾經出過錯調了一會 64 o->ch[!d]=k->ch[d];k->ch[d]=o; 65 o->upd();k->upd(); 66 k->fa=o->fa;o->fa=k;if(o->ch[!d]) o->ch[!d]->fa=o; 67 } 68 Node *st[300100];LL top; 69 void solvetag(Node *o) 70 { 71 while(!isroot(o)) st[++top]=o,o=o->fa; 72 st[++top]=o; 73 while(top) st[top--]->pd(); 74 } 75 void splay(Node *o) 76 { 77 solvetag(o); 78 Node *fa,*fafa;bool d1,d2; 79 while(!isroot(o)) 80 { 81 fa=o->fa;d1=(o==fa->ch[0]); 82 if(isroot(fa)) rotate(fa,d1); 83 else 84 { 85 fafa=o->fa->fa;d2=(fa==fafa->ch[0]);//要保證fa不是root之後才能獲取這兩個值,曾錯過 86 if(d1==d2) rotate(fafa,d1),rotate(fa,d1);//zig-zig,兩次相同方向的單旋,先把父親轉上去,再把自己轉上去 87 else rotate(fa,d1),rotate(fafa,d2);//zig-zag,兩次相反方向的單旋,連續兩次把自己轉上去 88 } 89 } 90 } 91 void access(Node *o) 92 { 93 for(Node *lst=NULL;o;lst=o,o=o->fa) 94 { 95 splay(o);//此處不pushdown是由於splay中保證進行過了 96 o->ch[1]=lst;o->upd();//註意upd 97 } 98 } 99 Node *gtop(Node *o) 100 { 101 access(o);splay(o); 102 for(;o->ch[0];o=o->ch[0],o->pd());//此處不在開始前pushdown(o)是由於splay中保證進行過了 103 splay(o);return o;//聽說這裏不splay一下也很難卡掉 104 } 105 void mtop(Node *o) {access(o);splay(o);o->rev^=1;} 106 void link(Node *x,Node *y) 107 { 108 if(gtop(x)==gtop(y)) return; 109 mtop(y);y->fa=x; 110 } 111 void cut(Node *x,Node *y) 112 { 113 mtop(x);access(y);splay(y); 114 if(y->ch[0]!=x||x->ch[1]) return;//如果x、y之間直接有邊,那麽上面一行的操作之後應當是x與y在單獨一棵splay中,那麽一定保證y左子節點是x且x沒有右子節點 115 x->fa=y->ch[0]=NULL;//註意,改的是x的父親和y的子節點(雖然x的確是樹的根,但是此時在splay上是y的子節點,不能搞混) 116 y->upd();//註意 117 } 118 LL query(Node *x,Node *y) 119 { 120 mtop(x);access(y);splay(y); 121 //if(gtop(y)!=x) return 0;//此題保證x與y連通,不需要 122 return y->sum; 123 } 124 void add(Node *x,Node *y,LL t) 125 { 126 mtop(x);access(y);splay(y); 127 y->padd(t); 128 } 129 void mul(Node *x,Node *y,LL t) 130 { 131 mtop(x);access(y);splay(y); 132 y->pmul(t); 133 } 134 } 135 LCT::Node *nd[300100]; 136 LL n,q;char tmp[20]; 137 int main() 138 { 139 LL i,x,y,t,x2,y2; 140 scanf("%lld%lld",&n,&q); 141 for(i=1;i<=n;i++) 142 { 143 nd[i]=LCT::getnode(); 144 nd[i]->mulv=1;nd[i]->dat=nd[i]->sum=1;nd[i]->sz=1; 145 } 146 for(i=1;i<n;i++) 147 { 148 scanf("%lld%lld",&x,&y); 149 LCT::link(nd[x],nd[y]); 150 } 151 while(q--) 152 { 153 scanf("%s",tmp); 154 switch(tmp[0]) 155 { 156 case +: 157 scanf("%lld%lld%lld",&x,&y,&t); 158 LCT::add(nd[x],nd[y],t); 159 break; 160 case -: 161 scanf("%lld%lld%lld%lld",&x,&y,&x2,&y2); 162 LCT::cut(nd[x],nd[y]);LCT::link(nd[x2],nd[y2]); 163 break; 164 case *: 165 scanf("%lld%lld%lld",&x,&y,&t); 166 LCT::mul(nd[x],nd[y],t); 167 break; 168 case /: 169 scanf("%lld%lld",&x,&y); 170 printf("%lld\n",LCT::query(nd[x],nd[y])); 171 } 172 } 173 return 0; 174 }

壓行後:

技術分享圖片
  1 #pragma GCC optimize("Ofast")
  2 #pragma GCC optimize("inline","fast-math","unroll-loops","no-stack-protector")
  3 #pragma GCC diagnostic error "-fwhole-program"
  4 #pragma GCC diagnostic error "-fcse-skip-blocks"
  5 #pragma GCC diagnostic error "-funsafe-loop-optimizations"
  6 #pragma GCC diagnostic error "-std=c++14"
  7 #include<cstdio>
  8 #include<algorithm>
  9 using namespace std;
 10 typedef long long LL;
 11 const LL md=51061;
 12 namespace LCT
 13 {
 14 struct Node
 15 {
 16     Node *ch[2],*fa;
 17     bool rev;
 18     LL addv,mulv;
 19     LL dat,sum,sz;
 20     void padd(LL x)
 21     {
 22         addv=(addv+x)%md;dat=(dat+x)%md;sum=(sum+x*sz)%md;
 23     }
 24     void pmul(LL x)
 25     {
 26         addv=addv*x%md;mulv=mulv*x%md;dat=dat*x%md;sum=sum*x%md;
 27     }
 28     void upd()
 29     {
 30         sum=((ch[0]?ch[0]->sum:0)+(ch[1]?ch[1]->sum:0)+dat)%md;
 31         sz=(ch[0]?ch[0]->sz:0)+(ch[1]?ch[1]->sz:0)+1;
 32     }
 33     void pd()
 34     {
 35         if(rev)
 36         {
 37             swap(ch[0],ch[1]);
 38             if(ch[0])    ch[0]->rev^=1;
 39             if(ch[1])    ch[1]->rev^=1;
 40             rev=0;
 41         }
 42         if(mulv!=1)
 43         {
 44             if(ch[0])    ch[0]->pmul(mulv);
 45             if(ch[1])    ch[1]->pmul(mulv);
 46             mulv=1;
 47         }
 48         if(addv)
 49         {
 50             if(ch[0])    ch[0]->padd(addv);
 51             if(ch[1])    ch[1]->padd(addv);
 52             addv=0;
 53         }
 54     }
 55 }nodes[300100];
 56 LL mem;
 57 Node *getnode()
 58 {
 59     return nodes+(mem++);
 60 }
 61 bool isroot(Node *x)
 62 {
 63     return (!x->fa)||((x->fa->ch[0]!=x)&&(x->fa->ch[1]!=x));
 64 }
 65 bool gson(Node *o)    {return o==o->fa->ch[1];}//獲得是父親的左兒子(返回0)還是右兒子(1),要求保證存在父親
 66 void rotate(Node *o,bool d)
 67 //在o子樹中執行d=0左旋,d=1右旋,在旋轉前不標記下傳,並將o父節點的對應子節點由o變為需要值,要求保證存在子樹(!d)
 68 {
 69     Node *k=o->ch[!d];if(!isroot(o))    o->fa->ch[gson(o)]=k;//註意這一句修改o父節點的要寫在前面,曾經出過錯調了一會
 70     o->ch[!d]=k->ch[d];k->ch[d]=o;
 71     o->upd();k->upd();
 72     k->fa=o->fa;o->fa=k;if(o->ch[!d])    o->ch[!d]->fa=o;
 73 }
 74 Node *st[300100];LL top;
 75 void solvetag(Node *o)
 76 {
 77     while(!isroot(o))    st[++top]=o,o=o->fa;
 78     st[++top]=o;
 79     while(top)    st[top--]->pd();
 80 }
 81 void splay(Node *o)
 82 {
 83     solvetag(o);
 84     Node *fa,*fafa;bool d1,d2;
 85     while(!isroot(o))
 86     {
 87         fa=o->fa;d1=(o==fa->ch[0]);
 88         if(isroot(fa))    rotate(fa,d1);
 89         else
 90         {
 91             fafa=o->fa->fa;d2=(fa==fafa->ch[0]);//要保證fa不是root之後才能獲取這兩個值,曾錯過
 92             if(d1==d2)    rotate(fafa,d1),rotate(fa,d1);//zig-zig,兩次相同方向的單旋,先把父親轉上去,再把自己轉上去
 93             else    rotate(fa,d1),rotate(fafa,d2);//zig-zag,兩次相反方向的單旋,連續兩次把自己轉上去
 94         }
 95     }
 96 }
 97 void access(Node *o)
 98 {
 99     for(Node *lst=NULL;o;lst=o,o=o->fa)
100     {
101         splay(o);
102         o->ch[1]=lst;o->upd();
103     }
104 }
105 Node *gtop(Node *o)
106 {
107     access(o);splay(o);
108     for(;o->ch[0];o=o->ch[0],o->pd());
109     splay(o);return o;
110 }
111 void mtop(Node *o)                {access(o);splay(o);o->rev^=1;}
112 void split(Node *x,Node *y)        {mtop(x);access(y);splay(y);}
113 void link(Node *x,Node *y)        {mtop(y);y->fa=x;}
114 void cut(Node *x,Node *y)        {split(x,y);x->fa=y->ch[0]=NULL;y->upd();}
115 LL query(Node *x,Node *y)        {split(x,y);return y->sum;}
116 void add(Node *x,Node *y,LL t)    {split(x,y);y->padd(t);}
117 void mul(Node *x,Node *y,LL t)    {split(x,y);y->pmul(t);}
118 }
119 LCT::Node *nd[300100];
120 LL n,q;char tmp[20];
121 int main()
122 {
123     LL i,x,y,t,x2,y2;
124     scanf("%lld%lld",&n,&q);
125     for(i=1;i<=n;i++)
126     {
127         nd[i]=LCT::getnode();
128         nd[i]->mulv=1;nd[i]->dat=nd[i]->sum=1;nd[i]->sz=1;
129     }
130     for(i=1;i<n;i++)
131     {
132         scanf("%lld%lld",&x,&y);
133         LCT::link(nd[x],nd[y]);
134     }
135     while(q--)
136     {
137         scanf("%s",tmp);
138         switch(tmp[0])
139         {
140         case +:
141             scanf("%lld%lld%lld",&x,&y,&t);
142             LCT::add(nd[x],nd[y],t);
143             break;
144         case -:
145             scanf("%lld%lld%lld%lld",&x,&y,&x2,&y2);
146             LCT::cut(nd[x],nd[y]);LCT::link(nd[x2],nd[y2]);
147             break;
148         case *:
149             scanf("%lld%lld%lld",&x,&y,&t);
150             LCT::mul(nd[x],nd[y],t);
151             break;
152         case /:
153             scanf("%lld%lld",&x,&y);
154             printf("%lld\n",LCT::query(nd[x],nd[y]));
155         }
156     }
157     return 0;
158 }
View Code

洛谷 P1501 [國家集訓隊]Tree II