Codeforces Round #922 (Div. 2) ABCD

A. Brick Wall

很直白的贪心,显然就是全放横着的砖最优,每行中最多能放 \(\lfloor \dfrac{m}{2} \rfloor\) 个,答案为 \(n \cdot \lfloor \dfrac{m}{2} \rfloor\)

B. Minimize Inversions

\(A : a \ \ \ \ \ xa,xb \ \ \ \ \ b \ \ \ \ \ ya,yb\)
\(B : c \ \ \ \ \ xc,xd \ \ \ \ \ d \ \ \ \ \ yc,yd\)
xa 为 ab 之间小于 a 的个数,ya 为 b 之后小于 a 的个数。
交换前的逆序对数 \(w1 = [(xa + ya) + yb] + [((xc + yc) + yd)]\)
交换前的逆序对数 \(w2 = [(xb + yb) + ya] + [((xd + yd) + yc)]\)
若交换后更优,则 \(xa + xc > xb + xd\)
按照此规律排序能够做到 \(O(n^2\log n)\)
构造一种方案满足 \(\forall a,\ b,\ c,\ d \ \ \ \ xa + xc \le xb + xd\)
\(cnt\)\(a, b\) 间元素总个数。
显然有 \(\forall x \in [0, cnt]\)
如果 A 有序,则 \(xa = 0, xb = cnt\)
此时 \(xc \le cnt + xd\),满足条件。

void solve() {
	int n; cin >> n;
	vector<int> a(n);
	vector<int> b(n);
	vector<int> c(n);
	for(int &x : a) cin >> x;
	for(int &x : b) cin >> x;
	iota(All(c), 0);
	sort(All(c), [&](int x, int y){
		return a[x] < a[y];
	});
	for(int x : c) cout << a[x] << ' '; cout << '\n';
	for(int x : c) cout << b[x] << ' '; cout << '\n';
}

D. Blocking Elements

题意:在 \(a\) 中取 \(m\) 个元素,将原数组划分为 \(m + 1\) 个子段(可以为空),问 \(m\) 个元素和与子段和中的最大值最小为多少。
二分答案。
考虑 \(f[i]\) 表示取第 \(i\) 个元素,且在前 \(i\) 个中取出元素和的最小值。

\[f[i] = a[i] + min(f[j]) \ \ \ \ (sum[i - 1] - sum[j] \le mid) \]

\(sum\) 为前缀和。
单调队列 \(O(n)\) 维护即可。

#include<bits/stdc++.h>
#define rep(i, a, b) for(int i = (a); i <= (b); ++ i)
#define per(i, a, b) for(int i = (a); i >= (b); -- i)
#define pb emplace_back
#define All(X) X.begin(), X.end()
using namespace std;
using ll = long long;
constexpr int N = 1e5 + 5;

ll n, a[N], f[N];
int q[N], hh, tt;

bool check(ll v) {
	ll ans = 1e15;
	q[0] = 0;
	hh = tt = 0;
	rep(i, 1, n) {
		while(hh <= tt && a[i - 1] - a[q[hh]] > v) ++ hh;
		f[i] = a[i] - a[i - 1] + f[q[hh]];
		if(a[n] - a[i] <= v) ans = min(ans, f[i]);
		while(hh <= tt && f[i] <= f[q[tt]]) -- tt;
		q[++ tt] = i;
	}
	return ans <= v;
}

void solve() {
	cin >> n;
	rep(i, 1, n) cin >> a[i], a[i] += a[i - 1];
	ll l = 0, r = 1e15;
	while(l < r) {
		ll mid = l + r >> 1;
		if(check(mid)) r = mid;
		else l = mid + 1;
	}
	cout << l << '\n';
}

int main() {
	ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
	int T = 1;
	cin >> T;
	while(T --) solve();
	return 0;
}
posted @ 2024-01-31 01:15  Lu_xZ  阅读(148)  评论(0编辑  收藏  举报