• BZOJ2002: [Hnoi2010]Bounce 弹飞绵羊(LCT)


    Description

    某天,Lostmonkey发明了一种超级弹力装置,为了在 他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏。游戏一开始,Lostmonkey在地上沿着一条直线摆上n个装置,每个装置设定初始弹力系数ki,当 绵羊达到第i个装置时,它会往后弹ki步,达到第i+ki个装置,若不存在第i+ki个装置,则绵羊被弹飞。绵羊想知道当它从第i个装置起步时,被弹几次 后会被弹飞。为了使得游戏更有趣,Lostmonkey可以修改某个弹力装置的弹力系数,任何时候弹力系数均为正整数。

    Input

    第 一行包含一个整数n,表示地上有n个装置,装置的编号从0到n-1,接下来一行有n个正整数,依次为那n个装置的初始弹力系数。第三行有一个正整数m,接 下来m行每行至少有两个数i、j,若i=1,你要输出从j出发被弹几次后被弹飞,若i=2则还会再输入一个正整数k,表示第j个弹力装置的系数被修改成 k。对于20%的数据n,m<=10000,对于100%的数据n<=200000,m<=100000

    Output

    对于每个i=1的情况,你都要输出一个需要的步数,占一行。

    Sample Input

    4
    1 2 1 1
    3
    1 1
    2 1 1
    1 1

    Sample Output

    2
    3

    解题思路:

    LCT,很显然要让 i 与 i 能到的点连边,yy一个不存在的点n+1,让所有点与它连边表示弹飞。

    更改时先Cut后Link

    最后查询时将n+1与x路径提取,查询重量即可(注意要-1^_^)

    代码:

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #define lll tr[spc].ch[0]
      5 #define rrr tr[spc].ch[1]
      6 #define ls ch[0]
      7 #define rs ch[1]
      8 const int N=300000;
      9 struct trnt{
     10     int ch[2];
     11     int lzt;
     12     int fa;
     13     int wgt;
     14     bool anc;
     15 }tr[N];
     16 int nx[N];
     17 int n,m;
     18 bool whc(int spc)
     19 {
     20     return tr[tr[spc].fa].rs==spc;
     21 }
     22 void pushup(int spc)
     23 {
     24     tr[spc].wgt=tr[lll].wgt+tr[rrr].wgt+1;
     25     return ;
     26 }
     27 void trr(int spc)
     28 {
     29     if(!spc)
     30         return ;
     31     std::swap(lll,rrr);
     32     tr[spc].lzt^=1;
     33     return ;
     34 }
     35 void pushdown(int spc)
     36 {
     37     if(tr[spc].lzt)
     38     {
     39         tr[spc].lzt=0;
     40         trr(lll);
     41         trr(rrr);
     42     }
     43     return ;
     44 }
     45 void recal(int spc)
     46 {
     47     if(!tr[spc].anc)
     48         recal(tr[spc].fa);
     49     pushdown(spc);
     50     return ;
     51 }
     52 void rotate(int spc)
     53 {
     54     int f=tr[spc].fa;
     55     bool k=whc(spc);
     56     tr[f].ch[k]=tr[spc].ch[!k];
     57     tr[spc].ch[!k]=f;
     58     if(tr[f].anc)
     59     {
     60         tr[spc].anc=1;
     61         tr[f].anc=0;
     62     }else
     63         tr[tr[f].fa].ch[whc(f)]=spc;
     64     tr[spc].fa=tr[f].fa;
     65     tr[f].fa=spc;
     66     tr[tr[f].ch[k]].fa=f;
     67     pushup(f);
     68     pushup(spc);
     69     return ;
     70 }
     71 void splay(int spc)
     72 {
     73     recal(spc);
     74     while(!tr[spc].anc)
     75     {
     76         int ft=tr[spc].fa;
     77         if(tr[ft].anc)
     78         {
     79             rotate(spc);
     80             return ;
     81         }
     82         if(whc(spc)^whc(ft))
     83             rotate(spc);
     84         else
     85             rotate(ft);
     86         rotate(spc);
     87     }
     88     return ;
     89 }
     90 void access(int spc)
     91 {
     92     int lst=0;
     93     while(spc)
     94     {
     95         splay(spc);
     96         tr[rrr].anc=1;
     97         tr[lst].anc=0;
     98         rrr=lst;
     99         pushup(spc);
    100         lst=spc;
    101         spc=tr[spc].fa;
    102     }
    103     return ;
    104 }
    105 void Mtr(int spc)
    106 {
    107     access(spc);
    108     splay(spc);
    109     trr(spc);
    110     return ;
    111 }
    112 void Link(int spc,int y)
    113 {
    114     access(spc);
    115     splay(spc);
    116     tr[spc].fa=y;
    117     return ;
    118 }
    119 void Cut(int x,int y)
    120 {
    121     Mtr(x);
    122     access(y);
    123     splay(x);
    124     tr[x].rs=0;
    125     tr[y].anc=1;
    126     tr[y].fa=0;
    127     return ;
    128 }
    129 void split(int x,int y)
    130 {
    131     Mtr(x);
    132     access(y);
    133     splay(y);
    134 }
    135 int dest(int i)
    136 {
    137     return (i+nx[i]>n)?(n+1):(i+nx[i]);
    138 }
    139 int main()
    140 {
    141     scanf("%d",&n);
    142     for(int i=1;i<=n+1;i++)
    143         tr[i].anc=1;
    144     for(int i=1;i<=n;i++)
    145     {
    146         scanf("%d",&nx[i]);
    147         Link(i,dest(i));
    148     }
    149     scanf("%d",&m);
    150     while(m--)
    151     {
    152         int i,j,k;
    153         scanf("%d",&i);
    154         if(i==1)
    155         {
    156             scanf("%d",&j);
    157             j++;
    158             split(j,n+1);
    159             printf("%d
    ",tr[n+1].wgt-1);
    160         }else{
    161             scanf("%d%d",&j,&k);
    162             j++;
    163             Cut(j,dest(j));
    164             nx[j]=k;
    165             Link(j,dest(j));
    166         }
    167     }
    168     return 0;
    169 }
  • 相关阅读:
    网络编程2018-4-23
    网络编程
    异常处理
    在Asp.net core使用配置Json创建动态目录树
    Asp.net Core中文转换成拼音
    解决Asp.Net core 控制台出现乱码的情况
    解决Asp.net Core中chtml文档中文乱码的问题
    取代Ajax.BeginForm的ajax使用方法
    将数据库模型放入到.Net Core的类库中
    如何使用Resource资源文件
  • 原文地址:https://www.cnblogs.com/blog-Dr-J/p/9639010.html
Copyright © 2020-2023  润新知