zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    Linux 学习 step by step (1)
    ubuntu server nginx 安装与配置
    ubuntu server samba服务器配置
    iOS app集成支付宝支付流程及后台php订单签名处理
    mac 连接windows 共享内容
    linux 文件查找,which,whereis,locate,find
    ubuntu server vsftpd 虚拟用户及目录
    ubuntu server 安装 mantis bug tracker 中文配置
    ubuntu server vsftpd 匿名用户上传下载及目录设置
    linux 用户管理,用户权限管理,用户组管理
  • 原文地址:https://www.cnblogs.com/lidaxin/p/5319501.html
Copyright © 2011-2022 走看看