题目描述
在游戏MC(我的世界)中,如果小麦碰到水流就会掉落,但是mc中的水不能无限流动,在同一高度一桶水往一个方向流最多可以流动8格(算上本身一格)。
但是如果流动过程中遇到了阶梯下降了高度,则从下降的那一格开始重新计算距离,所以根据这个原理可以设计一种自动收小麦机,只需要从最高处倒一桶水就可以把所有小麦变成掉落物。
这次小小航也根据这个原理建造了一个自动收小麦机,但是小小航并没有精确的计算台阶的位置,当小小航建造完后发现机器不能一次收集所有小麦,现在已知小小航的收小麦机总长为 n 格 ,水流可以流 k 格,每一格上的小麦数量为ai。
共有q次询问(每次询问之间互不影响),每次询问一个整数x,在第x格放一桶水共可以收获多少小麦。(水只会从高的一端流向低的一端)
样例输入
4 1 2
1 1 4 5
2 2 2 3
4
样例输出
10
样例描述
在第4格放出水流后,水流会流向第3格,由于第3格高度比第4格低,所以水流继续向左流向第2格,因为平地水流只能流2格,所以到达第2格后水流停止,收获的小麦数量为1 + 4 + 5 = 10
样例输入
5 2 2
1 1 4 5 1
2 2 3 3 4
4
3
样例输出
9
6
原题链接:
解题思路:
1、每一格最多能流到哪一格dp方程:
f[i]表示第i格最多能留多远,因此状态转移条件就是如果从第i格走k步能走到高度不同的点就可以等与前一个点走的+1,否则最多只能走min(i-1,k)步
f[i] = min(i,k);
if(h[i]>h[i-f[i]+1])
{
f[i] = max(f[i],f[i-1] + 1);
}
2、前缀和后的表示
从第i格走m步的话:sum[i]-sum[i-m]
理由是当前点(第i个点)也算一格
AC代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
typedef long long ll;
int f[N];
ll w[N];
int h[N];
int n,q,k;
int main()
{
cin >> n >> q >> k;
for(int i = 1;i<=n;i++)
{
cin >> w[i];
w[i] += w[i-1];
}
for(int i = 1;i<=n;i++) cin >> h[i];
for(int i = 1;i<=n;i++)
{
f[i] = min(i,k);
if(h[i]>h[i-f[i]+1])
{
f[i] = max(f[i],f[i-1] + 1);
}
}
// for(int i = 1;i<=n;i++) cout << f[i] <<' ';
//puts("");
while(q--)
{
int x;
cin >> x;
cout << w[x]-w[x-f[x]] << endl;
}
return 0;
}