洛谷 P3203 [HNOI2010]弹飞绵羊 || bzoj2002
Posted 哈
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷 P3203 [HNOI2010]弹飞绵羊 || bzoj2002相关的知识,希望对你有一定的参考价值。
看来这个lct板子的确没什么问题
好像还可以分块做
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 typedef long long LL; 5 namespace LCT 6 { 7 struct Node 8 { 9 Node *ch[2],*fa; 10 bool rev; 11 LL sz; 12 void upd() 13 { 14 sz=(ch[0]?ch[0]->sz:0)+(ch[1]?ch[1]->sz:0)+1; 15 } 16 void pd() 17 { 18 if(rev) 19 { 20 swap(ch[0],ch[1]); 21 if(ch[0]) ch[0]->rev^=1; 22 if(ch[1]) ch[1]->rev^=1; 23 rev=0; 24 } 25 } 26 }nodes[300100]; 27 LL mem; 28 Node *getnode() 29 { 30 return nodes+(mem++); 31 } 32 bool isroot(Node *x) 33 { 34 return (!x->fa)||((x->fa->ch[0]!=x)&&(x->fa->ch[1]!=x)); 35 } 36 bool gson(Node *o) {return o==o->fa->ch[1];}//获得是父亲的左儿子(返回0)还是右儿子(1),要求保证存在父亲 37 void rotate(Node *o,bool d) 38 //在o子树中执行d=0左旋,d=1右旋,在旋转前不标记下传,并将o父节点的对应子节点由o变为需要值,要求保证存在子树(!d) 39 { 40 Node *k=o->ch[!d];if(!isroot(o)) o->fa->ch[gson(o)]=k;//注意这一句修改o父节点的要写在前面,曾经出过错调了一会 41 o->ch[!d]=k->ch[d];k->ch[d]=o; 42 o->upd();k->upd(); 43 k->fa=o->fa;o->fa=k;if(o->ch[!d]) o->ch[!d]->fa=o; 44 } 45 Node *st[300100];LL top; 46 void solvetag(Node *o) 47 { 48 while(!isroot(o)) st[++top]=o,o=o->fa; 49 st[++top]=o; 50 while(top) st[top--]->pd(); 51 } 52 void splay(Node *o) 53 { 54 solvetag(o); 55 Node *fa,*fafa;bool d1,d2; 56 while(!isroot(o)) 57 { 58 fa=o->fa;d1=(o==fa->ch[0]); 59 if(isroot(fa)) rotate(fa,d1); 60 else 61 { 62 fafa=o->fa->fa;d2=(fa==fafa->ch[0]);//要保证fa不是root之后才能获取这两个值,曾错过 63 if(d1==d2) rotate(fafa,d1),rotate(fa,d1);//zig-zig,两次相同方向的单旋,先把父亲转上去,再把自己转上去 64 else rotate(fa,d1),rotate(fafa,d2);//zig-zag,两次相反方向的单旋,连续两次把自己转上去 65 } 66 } 67 } 68 void access(Node *o) 69 { 70 for(Node *lst=NULL;o;lst=o,o=o->fa) 71 { 72 splay(o);//此处不pushdown是由于splay中保证进行过了 73 o->ch[1]=lst;o->upd();//注意upd 74 } 75 } 76 Node *gtop(Node *o) 77 { 78 access(o);splay(o); 79 for(;o->ch[0];o=o->ch[0],o->pd());//此处不在开始前pushdown(o)是由于splay中保证进行过了 80 splay(o);return o;//听说这里不splay一下也很难卡掉 81 } 82 void mtop(Node *o) {access(o);splay(o);o->rev^=1;} 83 void link(Node *x,Node *y) 84 { 85 if(gtop(x)==gtop(y)) return; 86 mtop(y);y->fa=x; 87 } 88 void cut(Node *x,Node *y) 89 { 90 mtop(x);access(y);splay(y); 91 if(y->ch[0]!=x||x->ch[1]) return;//如果x、y之间直接有边,那么上面一行的操作之后应当是x与y在单独一棵splay中,那么一定保证y左子节点是x且x没有右子节点 92 x->fa=y->ch[0]=NULL;//注意,改的是x的父亲和y的子节点(虽然x的确是树的根,但是此时在splay上是y的子节点,不能搞混) 93 y->upd();//注意 94 } 95 LL query(Node *x,Node *y) 96 { 97 mtop(x);access(y);splay(y); 98 //if(gtop(y)!=x) return 0;//此题保证x与y连通,不需要 99 return y->sz; 100 } 101 } 102 LCT::Node *nd[300100]; 103 LL n,m;char tmp[20];LL a[300100]; 104 int main() 105 { 106 LL i,x,y,idx; 107 scanf("%lld",&n); 108 for(i=0;i<=n;i++) 109 { 110 nd[i]=LCT::getnode(); 111 nd[i]->sz=1; 112 } 113 for(i=0;i<n;i++) 114 { 115 scanf("%lld",&a[i]); 116 LCT::link(nd[i],nd[min(i+a[i],n)]); 117 } 118 scanf("%lld",&m); 119 for(i=1;i<=m;i++) 120 { 121 scanf("%lld%lld",&idx,&x); 122 if(idx==1) 123 { 124 printf("%lld\n",LCT::query(nd[x],nd[n])-1); 125 } 126 else 127 { 128 scanf("%lld",&y); 129 LCT::cut(nd[x],nd[min(x+a[x],n)]); 130 a[x]=y; 131 LCT::link(nd[x],nd[min(x+a[x],n)]); 132 } 133 } 134 return 0; 135 }
以上是关于洛谷 P3203 [HNOI2010]弹飞绵羊 || bzoj2002的主要内容,如果未能解决你的问题,请参考以下文章