• BZOJ 2002: [Hnoi2010]Bounce 弹飞绵羊 lct 动态树 splay


    http://www.lydsy.com/JudgeOnline/problem.php?id=2002

    http://blog.csdn.net/frods/article/details/52244250

    本来以为lct是很难的算法没想到这么简单。。。也可能只是这道题简单。

    看上去挺暴力的算法却有着很优秀的复杂度,很美丽了orz。

    做法就是每次查询把子节点连一条到根的通路,所有的儿子都在父亲右儿子上,再splay查询的点。此时查询的点的左儿子的size就是所求的距离。

    这个算法太神奇了orz。明明感觉有些粗笨简单但是透出朴实而容易ac的美,就像约翰内斯·维米尔的画,QAQ太令人愉悦了,QAQ谁会不喜欢splay呢。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 #include<cmath>
     6 using namespace std;
     7 const int maxn=200010;
     8 int n,m;
     9 int kid[maxn][2]={},fa[maxn]={},siz[maxn]={};
    10 inline bool CheckRoot(int x){return kid[fa[x]][0]!=x&&kid[fa[x]][1]!=x;}
    11 inline void updata(int x){
    12     siz[x]=1+siz[kid[x][0]]+siz[kid[x][1]];
    13 }
    14 void rotate(int x){
    15     int y=fa[x];int fy=fa[y];
    16     int l,r;
    17     l=kid[y][0]==x?0:1; r=l^1;
    18     if(!CheckRoot(y)){
    19         if(kid[fy][0]==y)kid[fy][0]=x;
    20         else kid[fy][1]=x;
    21     }fa[x]=fy;
    22     fa[y]=x;
    23     fa[kid[x][r]]=y;
    24     kid[y][l]=kid[x][r];kid[x][r]=y;
    25     updata(y);//updata(x);这里不需要updata(x)因为splay只updata一下就可以惹
    26 }
    27 void Splay(int x){
    28     while(!CheckRoot(x)){
    29         int y=fa[x];int fy=fa[y];
    30         if(!CheckRoot(y)){
    31             if((x==kid[y][0])^(y==kid[fy][0]))rotate(x);
    32             else rotate(y);
    33         }rotate(x);
    34     }updata(x);
    35 }
    36 void Access(int x){
    37     int y=0;
    38     while(x){
    39         Splay(x);kid[x][1]=y;
    40         updata(x);
    41         y=x;x=fa[x];
    42     }
    43 }
    44 void Cut(int x){
    45     Access(x);Splay(x);
    46     kid[x][0]=fa[kid[x][0]]=0;
    47 }
    48 void Link(int x,int y){
    49     Cut(x);
    50     fa[x]=y;
    51     updata(x);
    52 }
    53 int main(){
    54     scanf("%d",&n);
    55     int k,x,v;
    56     for(int i=1;i<=n;i++){
    57         scanf("%d",&v);
    58         fa[i]=i+v>n?0:i+v;
    59         siz[i]=1;
    60     }
    61     scanf("%d",&m);
    62     for(int i=1;i<=m;i++){
    63         scanf("%d%d",&k,&x);x++;
    64         if(k==1){
    65             Access(x);
    66             Splay(x);
    67             printf("%d
    ",siz[kid[x][0]]+1);
    68         }
    69         else{
    70             scanf("%d",&v);
    71             Link(x,x+v>n?0:x+v);
    72         }
    73     }
    74     return 0;
    75 }
    View Code

  • 相关阅读:
    发现WPF在Windows 7 的一个BUG ,多点触摸开发的注意了
    广度优先搜索 与 深度优先算法
    log4net window UAC下无法记录解决
    简单网页制作
    JS常用属性
    JS for循环、if判断、white循环。
    mysql 查询
    HTML学习随笔
    JS小练习
    mysql增删改
  • 原文地址:https://www.cnblogs.com/137shoebills/p/8604503.html
Copyright © 2020-2023  润新知