BZOJ 2002: [Hnoi2010]Bounce 弹飞绵羊 LCT

来源:互联网 发布:怎样开电信网络电视 编辑:程序博客网 时间:2024/04/20 10:00

题目大意:给出一个森林,支持两个操作:修改边,输出点到所在树的根的距离

LCT裸题。操作挺少的,只有Link和Cut操作(所以和到一起写了),维护一下Size即可。

#include <cstdio>#define N 200005using namespace std;struct Node{    Node *ch[2],*pa;    int s;    void maintain(){s=ch[0]->s+ch[1]->s+1;}    int dir(){return pa->ch[0]==this ? 0 : pa->ch[1]==this ? 1 : -1; }//判断当前点与父亲的关系    Node();}*null=new Node();Node p[N];Node :: Node(){pa=ch[0]=ch[1]=null; s=null?1:0;}void Rotate(Node* o,int d){    Node* k=o->ch[d^1]; int d2;    o->ch[d^1]=k->ch[d]; k->ch[d]->pa=o;    k->ch[d]=o;    o->maintain(); k->maintain();    if(~(d2=o->dir())) o->pa->ch[d2]=k;    k->pa=o->pa; o->pa=k;}void Splay(Node *o){    Node* p; int d;    while(~(d=o->dir())){        p=o->pa;        if(p->dir()==d) Rotate(p->pa,d^1);        Rotate(o->pa,d^1);    }    return ;}void Access(Node* o){//将o点到根的路径设置为“重链”    Node* p=null;    while(o!=null) {        Splay(o);        o->ch[1]=p; o->maintain();        p=o; o=o->pa;    }    return ;}void Link(Node* x,Node* y){    Access(x); Splay(x);        x->ch[0]->pa=null;        x->ch[0]=null; x->maintain();//Cut操作    x->pa=y;    return ;}int main(){    int n;    scanf("%d",&n);    null->ch[0]=null->ch[1]=null->pa=null;    for(int i=1;i<=n;i++){        int x;        scanf("%d",&x);        if(i+x<=n) p[i].pa=&p[i+x];    }    int m;    scanf("%d",&m);    while(m--){        int mode;        scanf("%d",&mode);        if(mode==1){            int x;            scanf("%d",&x); x++;            Access(&p[x]); Splay(&p[x]);            printf("%d\n",p[x].s);        }        else {            int x,y;            scanf("%d%d",&x,&y); x++;            if(x+y<=n) Link(&p[x],&p[x+y]);            else Link(&p[x],null);        }    }    return 0;}
0 0
原创粉丝点击