bzoj2002: [Hnoi2010]Bounce 弹飞绵羊(分块)
2017-08-15 10:59
399 查看
题意:
给一个序列,元素i的值x代表这个元素能跳到i+x位置。m次询问,对每个询问q,问q元素经过几次跳跃能跳出序列。询问中还有修改操作。
思路:
直接暴力的话,查询操作时间复杂度是O(n),修改操作O(1),最坏总时间O(m*n);题目意思就是序列中某个元素跳出这个序列需要的次数,那么我们可以把序列分割,对每个子序列,记录该序列中的每个元素跳出该序列需要的次数e[i],以及跳出这个序列后的位置en[i];如果把序列分成根号N块,那么查询和修改操作的时间都是根号N了。总时间O(m*根号n)
代码:
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
const int maxn = 200000+10;
int arr[maxn],e[maxn],en[maxn];
int main()
{
int n,m;
scanf("%d",&n);
for(int i = 0;i<n;i++)
{
scanf("%d",&arr[i]);
}
int len = sqrt(1.0*n);
for(int i = n-1;i>=0;i--)
{
int lin = min((i/len+1)*len,n);
int num = 1;
int pos = i;
pos += arr[i];
while(pos<lin)
{
num += e[pos];
pos = en[pos];
}
e[i]= num;
en[i] = pos;
}
scanf("%d",&m);
while(m--)
{
int type;
scanf("%d",&type);
if(type==1)
{
int pos;
scanf("%d",&pos);
int ans = 0;
while(pos<n)
{
ans += e[pos];
pos = en[pos];
}
printf("%d\n",ans);
}
else
{
int q,v;
scanf("%d%d",&q,&v);
arr[q] = v;
int lin = min((q/len+1)*len,n);
for(int i = q;i>=(q/len)*len;i--)
{
int num = 1;
int pos = arr[i]+i;
while(pos<lin)
{
num+=e[pos];
pos = en[pos];
}
e[i] = num;
en[i] = pos;
}
}
}
return 0;
}
给一个序列,元素i的值x代表这个元素能跳到i+x位置。m次询问,对每个询问q,问q元素经过几次跳跃能跳出序列。询问中还有修改操作。
思路:
直接暴力的话,查询操作时间复杂度是O(n),修改操作O(1),最坏总时间O(m*n);题目意思就是序列中某个元素跳出这个序列需要的次数,那么我们可以把序列分割,对每个子序列,记录该序列中的每个元素跳出该序列需要的次数e[i],以及跳出这个序列后的位置en[i];如果把序列分成根号N块,那么查询和修改操作的时间都是根号N了。总时间O(m*根号n)
代码:
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
const int maxn = 200000+10;
int arr[maxn],e[maxn],en[maxn];
int main()
{
int n,m;
scanf("%d",&n);
for(int i = 0;i<n;i++)
{
scanf("%d",&arr[i]);
}
int len = sqrt(1.0*n);
for(int i = n-1;i>=0;i--)
{
int lin = min((i/len+1)*len,n);
int num = 1;
int pos = i;
pos += arr[i];
while(pos<lin)
{
num += e[pos];
pos = en[pos];
}
e[i]= num;
en[i] = pos;
}
scanf("%d",&m);
while(m--)
{
int type;
scanf("%d",&type);
if(type==1)
{
int pos;
scanf("%d",&pos);
int ans = 0;
while(pos<n)
{
ans += e[pos];
pos = en[pos];
}
printf("%d\n",ans);
}
else
{
int q,v;
scanf("%d%d",&q,&v);
arr[q] = v;
int lin = min((q/len+1)*len,n);
for(int i = q;i>=(q/len)*len;i--)
{
int num = 1;
int pos = arr[i]+i;
while(pos<lin)
{
num+=e[pos];
pos = en[pos];
}
e[i] = num;
en[i] = pos;
}
}
}
return 0;
}
相关文章推荐
- BZOJ 2002: [Hnoi2010]Bounce 弹飞绵羊 分块
- [BZOJ]2002: [Hnoi2010]Bounce 弹飞绵羊 分块
- 【bzoj2002】【Hnoi2010】【Bounce】【弹飞绵羊】【分块】
- 【bzoj2002】[Hnoi2010]Bounce 弹飞绵羊 分块
- bzoj2002 [Hnoi2010]Bounce 弹飞绵羊 (分块)
- BZOJ 2002: [Hnoi2010]Bounce 弹飞绵羊 分块
- bzoj2002 [Hnoi2010]Bounce 弹飞绵羊【分块】
- bzoj 2002: [Hnoi2010]Bounce 弹飞绵羊(分块)
- 【分块】BZOJ2002(Hnoi2010)[Bounce 弹飞绵羊]题解
- [bzoj2002][Hnoi2010]Bounce弹飞绵羊——分块
- BZOJ 2002 [Hnoi2010]Bounce 弹飞绵羊(分块)
- [BZOJ 2002][Hnoi2010]Bounce 弹飞绵羊:分块|LCT
- 【分块】【LCT】bzoj2002 [Hnoi2010]Bounce 弹飞绵羊
- BZOJ 2002: [Hnoi2010]Bounce 弹飞绵羊(分块)
- 【bzoj2002】[Hnoi2010]Bounce 弹飞绵羊 分块/LCT
- bzoj2002 [Hnoi2010]Bounce 弹飞绵羊(lct/分块)
- 【BZOJ2002】[Hnoi2010]Bounce 弹飞绵羊 分块
- Bzoj 2002: [Hnoi2010]Bounce 弹飞绵羊(分块)
- _bzoj2002 [Hnoi2010]Bounce 弹飞绵羊【分块】
- BZOJ2002 [Hnoi2010]Bounce 弹飞绵羊 解题报告【数据结构】【分块】