BZOJ2002 弹飞绵羊

匿名 (未验证) 提交于 2019-12-03 00:43:02

title: BZOJ2002 弹飞绵羊
date: 2018-07-20 19:39:51
tags: 分块
---

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

就不能想一个好点的背景吗?

˼·

很好的想法题,一开始并没有看出来和分块有半毛钱关系。。。

经过WangZY dalao的指点后,知道了要记录本块的绵羊要花多少步跳到下一块,以及跳到下一块的坐标是什么。

深究其原因,我们是牺牲了query的时间来换取了修改的时间,由此避免修改时“牵一发而动全身”,平衡query和修改的时间(这本身也是分块的作用)

#include<bits/stdc++.h> #define M 200005 using namespace std; struct node{     int to;//到哪一个块      int step;//需要多少步  }dp[M]; int n,m,s;//块的大小  int A[M]; //分块,记录每个块会到达下一个哪个块,以及所需的步数  int query(int i){     int res=0,cur=i;     while(cur<n){         res+=dp[cur].step;         cur=dp[cur].to;     }      return res; } void up(int i){     if(i+A[i]>=n)dp[i].step=1,dp[i].to=n;     else if(i+A[i]>=(i/s+1)*s)dp[i].step=1,dp[i].to=i+A[i];     else dp[i].step=dp[i+A[i]].step+1,dp[i].to=dp[i+A[i]].to;  } void update(int x,int y){     A[x]=y;     for(int i=min(n-1,(x/s+1)*s);i>=(x/s)*s;i--)up(i); } int main(){     cin>>n;     s=sqrt(n);      for(int i=0;i<n;i++)         scanf("%d",&A[i]);     for(int i=n-1;i>=0;i--)up(i);     cin>>m;     for(int i=1;i<=m;i++){         int f,x,y;         scanf("%d",&f);         if(f==1){             scanf("%d",&x);             printf("%d\n",query(x));         }                else {             scanf("%d%d",&x,&y);             update(x,y);         }     }      return 0; } //想法题 

原文:https://www.cnblogs.com/zryabc/p/9348016.html

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!