zoukankan      html  css  js  c++  java
  • 【bzoj2002】[Hnoi2010]Bounce 弹飞绵羊 link-cut-tree

    2016-05-30 11:51:59

    用一个next数组,记录点x的下一个点是哪个

    查询时,moveroot(n+1),access(x),splay(x) ,输出size[ch[x][0]]即为答案

    更改时,cut(x,next[x]) link(x,min(x+k,n+1))

    记得splay旋转后要更新size

     1 #include<bits/stdc++.h>
     2 #define N 200005
     3 using namespace std;
     4 int read(){
     5   int x=0,f=1;char ch=getchar();
     6   while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     7   while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
     8   return x*f;
     9 }
    10 int n,m,next[N];
    11 namespace LCT{
    12   int ch[N][2],fa[N],sz[N];bool rev[N];
    13   inline bool isroot(int x){
    14     if(ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x)return 1;return 0;
    15   }
    16   inline void pushdown(int x){
    17     if(rev[x]){
    18       rev[ch[x][0]]^=1;rev[ch[x][1]]^=1;rev[x]=0;
    19       swap(ch[x][0],ch[x][1]);
    20     }
    21   }
    22   inline void pushup(int x){
    23     sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+1;
    24   }
    25   void rotate(int x){
    26     int y=fa[x],k=ch[y][1]==x;
    27     if(!isroot(y))ch[fa[y]][ch[fa[y]][1]==y]=x;
    28     fa[x]=fa[y];
    29     fa[ch[x][!k]]=y;
    30     fa[y]=x;
    31     ch[y][k]=ch[x][!k];
    32     ch[x][!k]=y;
    33     pushup(y);pushup(x);
    34   }
    35   void Pushdown(int x){
    36     if(!isroot(x))Pushdown(fa[x]);
    37     pushdown(x);
    38   }
    39   void splay(int x){
    40       Pushdown(x);
    41       for(int y=fa[x];!isroot(x);y=fa[x]){
    42         if(!isroot(y)){
    43             if((ch[fa[y]][ch[fa[y]][1]==y])!=(ch[y][1]==x))rotate(x);
    44             else rotate(y);
    45         }rotate(x);
    46     }
    47   }
    48   inline void access(int x){
    49     int y=0;
    50     while(x){
    51       splay(x);
    52       ch[x][1]=y;
    53       x=fa[y=x];
    54     }
    55   }
    56   inline void moveroot(int x){
    57     access(x);splay(x);rev[x]^=1;
    58   }
    59   inline void link(int x,int y){
    60       moveroot(x);fa[x]=y;splay(x);
    61   }
    62   inline void cut(int x,int y){
    63       moveroot(x);access(y);splay(y);ch[y][0]=fa[x]=0;
    64   }
    65   inline int query(int x){
    66       moveroot(n+1);access(x);splay(x);
    67       return sz[ch[x][0]];
    68   }
    69 }
    70 int main(){
    71   n=read();
    72   for(int i=1;i<=n;i++){
    73     int x=read();
    74     LCT::fa[i]=x+i;LCT::sz[i]=1;
    75     if(LCT::fa[i]>n)LCT::fa[i]=n+1;
    76     next[i]=LCT::fa[i];
    77   }
    78   m=read();
    79   while(m--){
    80     int t=read();
    81     if(t==1)printf("%d
    ",LCT::query(read()+1));
    82     else {
    83       int x=read(),y=read();x++;
    84       int t=min(n+1,x+y);
    85       LCT::cut(x,next[x]);LCT::link(x,t);next[x]=t;
    86     }
    87   }
    88   return 0;
    89 }
    View Code

    2002: [Hnoi2010]Bounce 弹飞绵羊

    Time Limit: 10 Sec  Memory Limit: 259 MB
    Submit: 7451  Solved: 3925
    [Submit][Status][Discuss]

    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
  • 相关阅读:
    剑指 Offer 59
    665. 非递减数列
    1423. 可获得的最大点数(滑动窗口)
    1208. 尽可能使字符串相等(双指针、滑动窗口)
    643. 子数组最大平均数 I(滑动窗口)
    剑指 Offer 52. 两个链表的第一个公共节点
    295. 数据流的中位数
    888. 公平的糖果棒交换(数组、哈希表)
    Seaborn绘图工具
    Office Politics
  • 原文地址:https://www.cnblogs.com/wjyi/p/5541926.html
Copyright © 2011-2022 走看看