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


    【题目链接】

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

    【题意】

        给定n个数的序列,i可以跳到i+k[i],需要能够修改k并可以查询跳出n需要的步数。

    【思路】

        把i->i+k看作一条边,则问题抽象为一个森林,越靠后的点离原树的根越近。

        考虑LCT维护大小siz。

        修改k的操作可以看作是断边与连边的操作。注意如果直接跳出n应该与null相连以切断原来的边。

      一次查询可以先Access使u到根的路径独立,然后splay将u调整至根查询siz。

    【代码】

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 using namespace std;
     5 
     6 const int N = 4e5+10;
     7 
     8 namespace LCT {
     9     
    10     struct Node {
    11         Node *ch[2],*fa;
    12         int siz;
    13         Node();
    14         void maintain() {
    15             siz=ch[0]->siz+ch[1]->siz+1;
    16         }
    17     } *null=new Node,T[N];
    18     Node::Node() { fa=ch[0]=ch[1]=null; siz=1; }
    19     void rot(Node* o,int d) {
    20         Node *p=o->fa;
    21         p->ch[d]=o->ch[d^1];
    22         o->ch[d^1]->fa=p;
    23         o->ch[d^1]=p;
    24         o->fa=p->fa;
    25         if(p->fa->ch[0]==p) 
    26             p->fa->ch[0]=o;
    27         else if(p->fa->ch[1]==p)
    28             p->fa->ch[1]=o;
    29         p->fa=o;
    30         p->maintain();
    31     }
    32     void splay(Node* o) {
    33         Node *nf,*nff;
    34         while(o->fa->ch[0]==o||o->fa->ch[1]==o) {
    35             nf=o->fa,nff=nf->fa;
    36             if(o==nf->ch[0]) {
    37                 if(nf==nff->ch[0]) rot(nf,0);
    38                 rot(o,0);
    39             } else {
    40                 if(nf==nff->ch[1]) rot(nf,1);
    41                 rot(o,1);
    42             }
    43         }
    44         o->maintain();
    45     }
    46     void Access(Node* o) {
    47         Node *son=null;
    48         while(o!=null) {
    49             splay(o);
    50             o->ch[1]=son;
    51             o->maintain();
    52             son=o; o=o->fa;
    53         }
    54     }
    55     void Link(Node* u,Node* v) {
    56         Access(u); splay(u);
    57         u->ch[0]->fa=null;
    58         u->ch[0]=null;
    59         u->fa=v;
    60         u->maintain();
    61     }
    62 
    63 }
    64 using namespace LCT;
    65 
    66 int n,m;
    67 
    68 int main()
    69 {
    70     null->fa=null->ch[0]=null->ch[1]=null;
    71     null->siz=0;
    72     scanf("%d",&n);
    73     int op,x,y;
    74     for(int i=1;i<=n;i++) {
    75         scanf("%d",&x);
    76         if(i+x<=n) T[i].fa=&T[i+x];
    77     }
    78     scanf("%d",&m);
    79     for(int i=1;i<=m;i++) {
    80         scanf("%d%d",&op,&x);
    81         x++;
    82         if(op==1) {
    83             Access(&T[x]); splay(&T[x]);
    84             printf("%d
    ",T[x].siz);
    85         } else {
    86             scanf("%d",&y);
    87             if(x+y<=n) Link(&T[x],&T[x+y]);
    88             else Link(&T[x],null);
    89         }
    90     }
    91     return 0;
    92 }
  • 相关阅读:
    [转]Javascript中prototype和constructor详解
    [转]SCIM输入启动遭遇“Failed to load x11 FrontEnd module. ”错误
    [转]搭建高效的symbols服务器
    编译 boost 1.52.0
    opensuse 11.4 安装slickedit 2012 完美支持中文
    【转】MyEclipse 6.5 大提速
    [转]VS2005生成pdb签名的问题
    理解泛型 从需求演变开始
    数学中一个很简单的组合 但用程序如何去实现呢?
    从零开始开发服务器控件
  • 原文地址:https://www.cnblogs.com/lidaxin/p/5319501.html
Copyright © 2020-2023  润新知