BZOJ 2002 [Hnoi2010]Bounce 弹飞绵羊 (LCT)

来源:互联网 发布:成都加工中心编程招聘 编辑:程序博客网 时间:2024/04/26 13:08

一棵有根树,支持两种操作:

1,查询指定节点深度

2,为指定节点换父亲


既然树形态改变了,那么就把一切都交给LCT吧。。

LCT的关键函数access()只有10行,但是加上了splay,调起来还是作死的节奏啊,吐血2天终于AC了

关于link-cut tree的复杂度,虽然不会证,但我能造出的极限数据是n个节点的完美二叉树,然后相邻两个询问是两个路径尽量不相同的叶子节点,使splay的功效降到最低,每次都要从叶子一步一步走到根,单次logn,那么就是nlogn的复杂度了。但是对于splay本身巨大的常数只能说一声:呵呵

这里的splay只是作为载体而存在,所以简化了一些操作过程,也因此失去了形如o->ch[1]->ch[0]这样提取区间的功能,但还是能够很方便的做到提取一段链

#include <stdio.h>#include <string.h>#include <algorithm>#include <time.h>using namespace std;const int N = 202000;int n;struct Node *nill;struct Node {        Node *ch[2],*fa;        int sz;        bool d() { return fa->ch[1]==this; }        bool is() { return fa==nill || fa->ch[0]!=this && fa->ch[1]!=this; }        void setc(Node *o,int c) {                ch[c] = o;                o->fa = this;                up();        }        void up() {                if (this==nill) return ;                sz = ch[0]->sz + ch[1]->sz + 1;        }        void rot() {                int c = d();                Node *tmp = fa;                tmp->setc(ch[c^1],c);                if (tmp->is()) fa = tmp->fa;                else tmp->fa->setc(this,tmp->d());                setc(tmp,c^1);                fa->up();        }        void splay() {                while (!is()) {                        if (!fa->is()) {                                d()==fa->d() ? fa->rot() : rot();                        }                        rot();                }        }        void access() {                Node *p = this,*q = nill;                while (p!=nill) {                        p->splay();                        p->setc(q,1);                        q = p;                        p = p->fa;                }                splay();        }}memo[N],*idx[N],*bat;void change(Node *a,Node *b) {        a->splay();        a->ch[0]->fa = a->fa;        a->setc(nill,0);        a->fa = b;}void newNode(Node *&o) {        o = bat ++;        o->ch[0] = o->ch[1] = o->fa = nill;        o->sz  =1;}void init() {        bat = memo;        newNode(nill); nill->sz = 0;}void show(Node *o) {        if (o==nill) return ;        show(o->ch[0]);        printf("%d ",o-memo);        show(o->ch[1]);}inline void read(int &x) {        char c; bool sig = 0;        for (c = getchar(); c<'0' || c>'9'; c = getchar()) if (c=='-') sig = 1;        for (x = c-'0',c = getchar(); c>='0' && c<='9'; c = getchar()) x = x*10+c-'0';        sig && (x=-x);}int main() {        //     freopen("in.txt","r",stdin);        while (scanf("%d",&n)==1) {                init();                for (int i = 0; i <= n; i ++) {                        newNode(idx[i]);                }                for (int i = 0; i < n; i ++) {                        int x;                        read(x);                        idx[i]->fa = idx[min(n,i+x)];                }                int nq;                read(nq);                while (nq--) {                        int op,a,b;                        read(op); read(a);                        if (op==1) {                                idx[a]->access();                                printf("%d\n",idx[a]->sz - 1);                        } else {                                read(b);                                b = min(n,a+b);                                change(idx[a],idx[b]);                        }                }        }        //        printf("%.6f\n",(double)clock()/CLOCKS_PER_SEC);        return 0;}


0 0
原创粉丝点击