bzoj 3043 IncDec Sequence 差分
程序员文章站
2022-07-12 17:58:14
...
题面
解法
模型转化非常精妙
- 将区间,可以变成在差分数组第个位置,在第个位置
- 那么,我们可以考虑将问题转化一下,变成给定个数,每一次可以将某一个数或,另一个数可以不操作,否则做和第一个数相反的操作。问至少多少次这个数列变成全0
- 考虑一个贪心的解法,显然是每一次对一个负数,对一个正数,如果不存在对应的正数或负数,直接自己加或减变成0
- 显然,这个方法能保证答案是最小的,而且每一次操作都可以对应一个区间的加减
- 那么,我们设
- 根据上述贪心算法,显然最少的操作次数就是
- 那么,我们再考虑一下最后会出现多少种不同的序列。显然,在正数或负数全部被消去后,剩下的可以随意安排给或者,所以方案数就是
- 时间复杂度:
代码
#include <bits/stdc++.h>
#define int long long
#define N 100010
using namespace std;
template <typename node> void chkmax(node &x, node y) {x = max(x, y);}
template <typename node> void chkmin(node &x, node y) {x = min(x, y);}
template <typename node> void read(node &x) {
x = 0; int f = 1; char c = getchar();
while (!isdigit(c)) {if (c == '-') f = -1; c = getchar();}
while (isdigit(c)) x = x * 10 + c - '0', c = getchar(); x *= f;
}
int a[N], b[N];
main() {
int n; read(n);
for (int i = 1; i <= n; i++) read(a[i]);
for (int i = 2; i <= n; i++) b[i] = a[i] - a[i - 1];
int s1 = 0, s2 = 0;
for (int i = 2; i <= n; i++)
if (b[i] > 0) s1 += b[i]; else s2 -= b[i];
cout << max(s1, s2) << "\n" << abs(s1 - s2) + 1 << "\n";
return 0;
}
上一篇: 读《 ScalaTest 》有感
下一篇: eclipse工作空间设置(按需添加)