C:我们可以发现对于n为奇数的情况,只有一种可能,那就是2,4,---n-1为cool,所以直接处理就好,对于n为偶数来说比较困难,但通过其给的数据可以发现我们至多存在一个地方在两个cool中有两个不为cool的地方
(来自codeforces #809 C)
以给的数据为例子 在第2个和第4个之间有连续两个不为cool的地方,我们将其左右移动就可以找到规律:只能在首位为奇数的连续两个才可以满足最大的cool数,所以接下来只要将这两边分为两段,找最大就好了,可能不太清楚
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
#define int long long
const int maxn = 2e5 + 10;
int a[maxn], n, m;
int b[maxn];//代表将i维护位cool的花费
int dpfroce[maxn], dpback[maxn];
void solve()
{
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
if (n % 2)
{
int ans = 0;
for (int i = 2; i <= n; i += 2)
{
if (a[i] > a[i - 1] && a[i] > a[i + 1])
ans+= 0;
else if (a[i] <= a[i - 1] && a[i] > a[i + 1])
{
ans+= a[i - 1] - a[i] + 1;
}
else if (a[i] > a[i - 1] && a[i] <= a[i + 1])
{
ans+= a[i + 1] - a[i] + 1;
}
else
{
ans+= max(a[i - 1] - a[i] + 1, a[i + 1] - a[i] + 1);
}
}
cout << ans << endl;
return;
}
else
{
for (int i = 2; i <n; i++)
{
if (a[i] > a[i - 1] && a[i] > a[i + 1])
b[i] = 0;
else if (a[i] <= a[i - 1] && a[i] > a[i + 1])
{
b[i] = a[i - 1] - a[i] + 1;
}
else if(a[i]>a[i-1]&&a[i]<=a[i+1])
{
b[i] = a[i + 1] - a[i] + 1;
}
else
{
b[i] = max(a[i - 1] - a[i] + 1, a[i + 1] - a[i] + 1);
}
}
for (int i = 1; i <= n + 1; i++)
dpback[i] = dpfroce[i] = 0;
for (int i = n - 1; i >= 2; i--)
{//代表将i后面均维护位最大cool的情况
dpback[i] = dpback[i + 2] + b[i];
}
for (int i = 2; i <= n - 1; i++)
{
dpfroce[i] = dpfroce[i - 2] + b[i];
}
int ans =min(dpback[3],dpfroce[n-2]);
int now = 0;
for (int i = 3; i <n - 1; i += 2)
{
ans = min(ans, dpfroce[i - 1] + dpback[i +2]);
}
cout << ans << endl;
}
}
signed main()
{
int t;
cin >> t;
while (t--)
solve();
}
D1:其实刚刚开始看的时候我是想每次变动最大值,来更新答案的,后来发现这样做可能有点不太好处理就没写了,这里给官方答案的一个解释:
首先是最大值-最小值,我们需要找到最大和最小值,这类似找一段区间的那种感觉,我们可以像处理找一段合法区间问题那样,将左端点固定,枚举右端点这类做法,我们可以枚举最小值,并在保持最小值的基础上找靠近最小值的最大值来更新答案
#include<iostream>
#include<algorithm>
#include<map>
#include<vector>
using namespace std;
#define int long long
const int maxn = 3e3 + 10;
int a[maxn],n,k;
void solve()
{
cin >> n >> k;
map<int, int>m;
vector<int>v;
for (int i = 1; i <= n; i++) {
cin >> a[i];
for (int j = 1; j <= k; j++)
{
if (a[i] / j <= a[1] && m.count(a[i] / j) == 0)
{
m[a[i] / j] = 1;
v.push_back(a[i] / j);
}
}
}
int ans = 1e18;
for (auto x : v)
{
int maxx = x;
for (int i = 1; i <= n; i++)
{
int p = min(k, (x ? (a[i] /x) : k));//保证了a[i]/p是最接近x的
maxx = max(maxx, a[i] / p);
}
ans = min(ans, maxx - x);
}
cout << ans << endl;
}
signed main()
{
int t;
cin >> t;
while (t--)
solve();
}