社区讨论
站外题贪心求证(悬三关)
学术版参与者 5已保存回复 10
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 10 条
- 当前快照
- 1 份
- 快照标识符
- @lufjp88s
- 此快照首次捕获于
- 2024/03/31 21:16 2 年前
- 此快照最后确认于
- 2024/03/31 21:39 2 年前
题目大意:
给定一个长度为 的数组 ,你可以将任意数加一,不限次数,求最终排列里的逆序对的最少数量。
思路:
先离散化,如果 加一,那么逆序对的数量必然会增加减少等于 的数的个数(设其为 ),增加后面等于 的数的个数(设其为 ),贪心如果 ,那么将 加一,初始逆序对用树状数组维护。
代码:
CPP#include <bits/stdc++.h>
using namespace std;
using LL = long long;
using PII = pair<LL, LL>;
const LL kMaxN = 1e6 + 5;
LL n, idx, ans, a[kMaxN], fr[kMaxN], bc[kMaxN], b[kMaxN], cnt[kMaxN];
template <class T>
struct BIT {
T c[kMaxN] = {0};
T query(LL x) {
T sum = 0;
for (; x; x -= x & -x) {
sum += c[x];
}
return sum;
}
void update(LL x, T s) {
for (; x <= 2e5; x += x & -x) {
c[x] += s;
}
}
};
signed main() {
cin >> n;
for (LL i = 1; i <= n; i++) {
cin >> a[i];
b[++idx] = a[i];
}
sort(b + 1, b + idx + 1);
for (LL i = 1; i <= n; i++) {
a[i] = lower_bound(b + 1, b + idx + 1, a[i]) - b;
}
for (LL i = n; i; i--) {
bc[i] = cnt[a[i]], cnt[a[i]]++;
}
memset(cnt, 0, sizeof cnt);
BIT<LL> tr;
for (LL i = 1; i <= n; i++) {
ans += i - 1 - tr.query(a[i]);
tr.update(a[i], 1);
}
for (LL i = 1; i <= n; i++) {
fr[i] = cnt[a[i] + 1];
if (fr[i] > bc[i]) {
ans = ans - fr[i] + bc[i];
}
cnt[a[i] + (fr[i] > bc[i])]++;
}
cout << ans;
return 0;
}
当然巨佬们有更好解法发在楼下。
回复
共 10 条回复,欢迎继续交流。
正在加载回复...