题目大意:
假定给出一个包含
个整数的数组
,包含
个整数的数组
,与整数
。其中
数组中的整数均在区间
中。
用下面的算法对
进行
变换(
):
sum = 0
for i = 1 to N
index = min{ ID[i], ID[i+1] }
sum = sum + A[index]
将数组A往右循环移动R位
将数组A内所有的数取相反数
for i = 1 to N
index = max{ ID[i], ID[i+1] }
index = index + 1
sum = sum + A[index]
将数组A往右循环移动R位
给出数组
以及整数
,但没有给出数组
。
在对数组
进行了
算法后,变量
的可能出现的最大值数多少?
分析:
被毒瘤题暴奶
可以发现,
对答案的贡献只有
,可以考虑dp
设
为前
个
,第
个位置选数
作为
的最大
值
可以推出
是已经位移好了的,
定义
表示
是由哪个数转换而来
考虑两种情况
, 则
, 则
而
,
与
无关,可以预处理。
代码:
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#define fo(i, j, k) for (int i = j; i <= k; i++)
#define fw(i, j, k) for (int i = j; i >= k; i--)
#define inf 0x7fffffff
#define N 3005
using namespace std;
int f[N][N], g[N][N], a[N], n, r;
void Work(int x, int y) {
if (x != 0) Work(x - 1, g[x][y]);
printf("%d ", y + 1);
}
int main() {
scanf("%d %d", &n, &r);
fo(i, 0, n-1) scanf("%d", &a[i]);
fo(i, 1, n)
fo(j, 0, n-2) f[i][j] = -inf;
fo(i, 1, n) {
int ans = -inf, num;
fo(j, 0, n-2) {
if (ans < f[i-1][j] + a[((j - (i-1) * r) % n + n) % n]) {
ans = f[i-1][j] + a[((j - (i-1) * r) % n + n) % n];
num = j;
}
if (f[i][j] < ans - a[((j - (i-1) * r + 1) % n + n) % n]) {
f[i][j] = ans - a[((j - (i-1) * r + 1) % n + n) % n];
g[i][j] = num;
}
}
ans = -inf;
fw(j, n-2, 0) {
if (ans < f[i-1][j] - a[((j - (i-1) * r + 1) % n + n) % n]) {
ans = f[i-1][j] - a[((j -(i-1) * r + 1) % n + n) % n];
num = j;
}
if (f[i][j] < ans + a[((j - (i-1) * r) % n + n) % n]) {
f[i][j] = ans + a[((j - (i-1) * r) % n + n) % n];
g[i][j] = num;
}
}
}
int ans = -inf, num;
fo(i, 0, n-2)
if (ans < f[n][i])
ans = f[n][i], num = i;
printf("%d\n",ans);
Work(n, num);
}