原题链接
题目
输入
3
3 0
1 3 2
2 0
1 2
7 0
1 2 5 4 3 6 7
输出
3
2
9
Note
In third test case we can build an army in such way: [1 2 5 4 3 6 7], its strength will be 5−3+7=9.
题意
从原数组a中找k个数,组成b数组,要保证 1≤b1<b2<⋯<bk≤n,
然后进行b1−b2+b3−b4+… .操作,求操作后的最大值是多少。
思路
减完之后要加,加完之后又要减,所以用dp保留上一步操作的结果,与下次操作后做对比,取最大值。
dp公式:
dp[i][0] = max (dp[i - 1][0], dp[i - 1][1] + a[i]);
dp[i][1] = max (dp[i - 1][1], dp[i - 1][0] - a[i]);
推导
dp[i][0] = max (dp[i - 1][0], dp[i - 1][1] + a[i]);
//在一次减操作后可以选择加一个数,也可以选择不加任何数
//dp[i - 1][0]表示在上一次减操作后不加任何数,维持原状态
//dp[i - 1][1] + a[i]表示在上一步减操作后加一个数
dp[i][1] = max (dp[i - 1][1], dp[i - 1][0] - a[i]);
//同理,在一次加操作后可以选择不减任何数,也可以选择减去一个数
代码:
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <utility>
#include <stack>
#include <queue>
#include <cmath>
#include <map>
#include <list>
#include <set>
#include <cstdlib>
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 3e5 + 10;
const int N = 10010;
const int INF = 0x3f3f3f3f;
const ll LNF = 0x3f3f3f3f3f3f3f3f;
const ll mod = 1e9 + 7;
const double eps = 10e-6;
const double PI = 3.14159265358979323;
typedef pair<int, int> PII;
priority_queue<int, vector<int>, less<int> >q;
priority_queue<int, vector<int>, greater<int> >qq;
ll a[maxn];//存放数组值
ll dp[maxn][2];//用于存放当前状态,dp[][0]表示进行加操作,dp[][1]表示进行减操作
int main () {
int t;
scanf ("%d", &t);
while (t--) {
int n, q;
scanf ("%d %d", &n, &q);
for (int i = 1; i <= n; i++) {
scanf ("%lld", &a[i]);
}
for (int i = 1; i <= n; i++){
//因为多组输入,所以dp清空数组
dp[i][0] = 0;
dp[i][1] = 0;
}
for (int i = 1; i <= n; i++){
dp[i][0] = max (dp[i - 1][0], dp[i - 1][1] + a[i]);
//在一次减操作后可以选择加一个数,也可以选择不加任何数
//dp[i - 1][0]表示在上一次减操作后不加任何数,维持原状态
//dp[i - 1][1] + a[i]表示在上一步减操作后加一个数
dp[i][1] = max (dp[i - 1][1], dp[i - 1][0] - a[i]);
//同理,在一次加操作后可以选择不减任何数,也可以选择减去一个数
}
ll ans = max (dp[n][0], dp[n][1]);
printf ("%lld\n", ans);
}
return 0;
}