动态树第一次攻关

动态树

  动态的维护 树上的很多条链。这些链组成了这棵树。。

  要熟练掌握splay  splay 是为了快速的将这条链打通。

 access 利用splay 完成打通路径。

  还要理解 那些 链的性质

 就差不多了。。。。

下面是 bzoj 2002 弹飞绵羊那道题的写法。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int max_point=200005;
struct str
{
    int c[2];//0是左
    int size;
    int pathparent; //实际的父节点
    int p;  //
    bool d;
}e[max_point];
int n,m,temp,num,tot=0;
void upd(int x)
{
    e[x].size=e[e[x].c[1]].size+e[e[x].c[0]].size+1;
}
void sc(int x,int d,int y)//x的d孩子是y
{
    e[x].c[d]=y;
    e[y].p=x;
    e[y].d=d;
    //e[y].pathparent=0; //y没有pathparent
}
void rot(int x)
{
    int y=e[x].p;
    bool d=e[x].d;
    if(!e[y].p) //如果y没有父亲
    {
        e[x].p=0; 
        e[x].pathparent=e[y].pathparent; //表明把x旋转到根了。
        e[y].pathparent=0;  //*****这里必须要有。超时应该就是这里。
    }
    else sc(e[y].p,e[y].d,x);
    sc(y,d,e[x].c[!d]); 
    sc(x,!d,y);
    upd(y); 
}
void splay(int x)
{
    int p1,p2;
    while(p1=e[x].p)
    {
        if(p2=e[p1].p) //如果p1 有父节点
        {
            if(e[x].d==e[p1].d)
                rot(p1),rot(x);
            else
                rot(x),rot(x);
        }
        else //如果p1没有父节点,只旋转1次
            rot(x);
    }
    upd(x);
}
void access(int x)
{
    int y=x;
    x=0;  //起点的右孩子要断掉
    while(y)  //从当前点出发,将相应的pathparent修改好。
    {
        splay(y);
        e[e[y].c[1]].pathparent=y;  //把y的后继链断掉
        e[e[y].c[1]].p=0;
        sc(y,1,x); //让y的右孩子是x
        e[x].pathparent=0;
        upd(y);
        x=y;
        y=e[y].pathparent;
    }
}
void search()
{
    scanf("%d",&temp);temp+=1;
    access(temp);
    splay(temp);
    printf("%d\n",e[e[temp].c[0]].size);
}
void change()
{
    scanf("%d%d",&temp,&num);temp+=1;
    access(temp);
    splay(temp);
    int son=e[temp].c[0];

    e[son].p=0;
    sc(temp,0,0); //将temp的左子树剪掉
    if(temp+num>n)num=n+1-temp;  //将新边连上。
    e[temp].pathparent=temp+num;
    upd(temp); 

}
int main()
{
    freopen("add.in","r",stdin);
    freopen("add.out","w",stdout);
    scanf("%d",&n);
    memset(e,0,sizeof(e));
    e[n+1].size=1;
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&temp);
        if(temp+i>n)
            e[i].pathparent=n+1;
        else e[i].pathparent=temp+i;
        e[i].size=1;
    }
    scanf("%d",&m);
    while(m--)
    {
        scanf("%d",&temp);
        if(temp==1)
            tot++,search();
        else
            change();
    }
    fclose(stdin);fclose(stdout);
    return 0;
}

 

posted @ 2013-07-01 14:54  sharpland  阅读(71)  评论(0)    收藏  举报