bzoj2002: [Hnoi2010]Bounce 弹飞绵羊

块状链表。维护一个点f[i]次能到达下一个块,和到哪个位置。

#include<cstdio>
#include<cmath>
using namespace std;
const int maxn = 400000 + 100;

int k[maxn],jump[maxn],st[maxn],belong[maxn],f[maxn];
int n,m,tot=1;

void build() {
  scanf("%d",&n);
  int len = (int)sqrt(n);
  for(int i=0,j=0;i<n;i++) {
    j++;
    if(j==len+1) {
      j=1;
      tot++;
      st[tot]=i; 
    }
    belong[i]=tot;
    scanf("%d",&k[i]);
  }
  belong[n]=tot+1;
  for(int i=n-1;i>=0;i--) {
    if(i+k[i]>=st[belong[i]+1]) {
        f[i]=1;
        jump[i]=i+k[i];
    }
    else {
        f[i]=f[i+k[i]]+1;
        jump[i]=jump[i+k[i]];
    }
  }
}

void change(int x,int c) {
  k[x]=c;
  for(int i=x;i>=st[belong[x]];i--) {
    if(i+k[i]>=st[belong[i]+1]) {
        f[i]=1;
        jump[i]=i+k[i];
    }
    else {
        f[i]=f[i+k[i]]+1;
        jump[i]=jump[i+k[i]];
    }
  } 
}

void solve() {
  scanf("%d",&m);
  for(int i=1,t,x,c;i<=m;i++) {
    scanf("%d%d",&t,&x); 
    if(t==1) {
      int res=0;
      while(x<n) {
        res+=f[x];
        x=jump[x];
        }
    printf("%d\n",res);
    }
    else {
        scanf("%d",&c);
        k[x]=c;
          for(int i=x;i>=st[belong[x]];i--) {
          if(i+k[i]>=st[belong[i]+1]) {
              f[i]=1;
            jump[i]=i+k[i];
          }
          else {
              f[i]=f[i+k[i]]+1;
            jump[i]=jump[i+k[i]];
          }
        } 
    }
  }
}

int main() {
  build();
  solve();
  
  return 0;
}
posted @ 2016-05-01 21:16  invoid  阅读(180)  评论(0编辑  收藏  举报