H
AC代码:
#include <iostream>
#include <algorithm>
using namespace std;
using ll = long long;
const int N = 1e6 + 5;
ll a[N];
ll dp1[N], dpl[N]; //dp1[i]维护前i只需要砍的次数,dpl[i]代表以第i只为最左边挥刀次数。
ll dp2[N], dpr[N]; //dp2[i]维护后i只需要砍的次数,dpr[i]代表以第i只为最右边挥刀次数。
int main()
{
ios::sync_with_stdio(false), cin.tie(0);
int n;
cin >> n;
for (int i = 1; i <= n; i++)
cin >> a[i];
dp1[1] = a[1];
dpl[1] = a[1];
ll k;
//cout << dp1[1] << ' ';
for (int i = 2; i <= n; i++)
{
k = a[i] - (dpl[i - 1] + dpl[i - 2]);
dp1[i] = k <= 0 ? dp1[i - 1] : dp1[i - 1] + k;
dpl[i] = k <= 0 ? 0 : k;
//cout << dp1[i] << ' ';
}
//cout << '\n';
dp2[n] = a[n];
dpr[n] = a[n];
//cout << dp2[n] << ' ';
for (int i = n - 1; i >= 1; i--)
{
k = a[i] - (dpr[i + 1] + dpr[i + 2]);
dp2[i] = k <= 0 ? dp2[i + 1] : dp2[i + 1] + k;
dpr[i] = k <= 0 ? 0 : k;
//cout << dp2[i] << ' ';
}
// cout << '\n';
ll ans = 1e18;
for (int i = 1; i <= n - 1; i++)
{
ans = min(ans, dp1[i - 1] + dp2[i + 2]);
}
cout << ans << '\n';
}
贪心题,比赛中想到了贪心没有想到贪心的方式。一直执着于少挥空刀,导致走偏了。
实际上可以换个方向考虑,从第一只开始考虑,由于最后其血量一定为0,故考虑砍他的方式,易知将1,2,3一起砍对结果的贡献最大,所以由第一只一直向后砍,每次砍最左边的直到其血量为0,既可以得到最优解(从最右边到最左边一样),考虑两个dp维护来降低时间复杂度即可。
C
AC代码:
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 3e6 + 5;
int a[N], b[N];
int main()
{
ios::sync_with_stdio(false), cin.tie(0);
int n;
cin >> n;
for (int i = 1; i <= n; i++)
cin >> a[i] >> b[i];
int A = 0;
int B = 0;
long long ans = 0;
int maxx, minn;
for (int i = 0; i < n; i++)
{
maxx = max(a[i], b[i]);
minn = min(a[i + 1], b[i + 1]);
if (maxx <= minn)
{
ans += minn - maxx + 1;
if (a[i] == b[i])
ans--;
}
}
cout << ans << '\n';
return 0;
}
竞赛最重要的是解决问题的思路,重点是要用什么方式去解决一个问题,当察觉到方式过于复杂时能否及时转换思路。