Educational Codeforces Round 19 E. Array Queries(DP+思维)(妙题)

题目链接
在这里插入图片描述
题意:给定初始数组a,m个询问,每次询问给出q和k,定义每次操作q=q+a【q】+k,求多少次操作后q>n。
思路:超棒的思维题,自己还在那怎么想莫队,我们可以发现我们其实可以把k的操作给变小的,我们先求出k小于sqrt(maxn)的时候,k不超过350,那么我们定义一下dp【i】【j】表示q为i,j为k时的最小操作次数,转移方程为dp【i】【j】=dp【i+a【i】+j】+1,我们发现k小于350的时候我们已经预处理好了,可以O(1)查询了,但k大于300怎么办?仔细思考一下,当k大于350的时候,它移动到大于n的时候最多也是maxn/sqrt(maxn)是不是,既然常数这么小,直接暴力就好了。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+1;
const int N=sqrt(maxn)+2;
int dp[maxn][N],a[maxn];
int main()
{
	int n,m,q,k;
	scanf("%d",&n);
	for(int i=1;i<=n;++i) scanf("%d",&a[i]);
	for(int i=n;i>=1;--i)
	{
		for(int j=1;j<=N;++j)
		if(i+a[i]+j>n) dp[i][j]=1;
		else dp[i][j]=dp[i+a[i]+j][j]+1;
	}
	scanf("%d",&m);
	while(m--)
	{
		scanf("%d %d",&q,&k);
		if(k<=N) {
			printf("%d\n",dp[q][k]);
			continue;
		}
		int ans=0;
		while(q<=n) ans++,q=q+a[q]+k;
		printf("%d\n",ans);
	}
}
发布了328 篇原创文章 · 获赞 1 · 访问量 9099

猜你喜欢

转载自blog.csdn.net/qq_42479630/article/details/105209621