「题解」Codeforces Round 980 (Div. 2)
before
\(A \sim D\) 的题解
A. Profitable Interest Rate
Problem
Sol&Code
数学题,有 \(a - x \geq b - 2x\),得 \(x = b - a\)。
特判 \(a \geq b\) 以及 \(a < x\) 的情况即可。
#include <bits/stdc++.h>
#define M 10001
#define N 100001
typedef long long ll;
typedef std::pair<int, int> pii;
int T, a, b;
int main() {
scanf("%d", &T);
while (T--) {
scanf("%d %d", &a, &b);
if (a >= b) printf("%d\n", a);
else {
int x = b - a;
printf("%d\n", std::max(0, a - x));
}
}
return 0;
}
B. Buying Lemonade
Problem
Sol&Code
一种最优的策略是,首先对已知还有剩余的所有按钮按当前最少的那个次数,然后用一定的次数排除没有库存的按钮,重复执行上述步骤。
#include <bits/stdc++.h>
#define M 10001
#define N 200001
typedef long long ll;
typedef std::pair<int, int> pii;
int T, n, k, a[N];
int main() {
scanf("%d", &T);
while (T--) {
scanf("%d %d", &n, &k);
for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
std::sort(a + 1, a + n + 1);
long long ans = 0, now = 1, minu = 0;
while (k > 0) {
while (now < n && a[now] <= minu) ++now, ++ans;
a[now] -= minu;
minu += a[now];
int t = std::min((long long)std::ceil(1.0 * k / a[now]), n - now + 1);
ans += t * a[now];
k -= t * a[now];
}
printf("%lld\n", ans + k);
}
return 0;
}
C. Concatenation of Arrays
Problem
Sol&Code
考虑对于一定顺序排列的元组,交换当中相邻的两个元组,对于这俩两侧的元组贡献的逆序对数没有影响。
考虑这俩如何排序更优,按元组内的数据和从小到大排。
#include <bits/stdc++.h>
#define M 10001
#define N 100001
typedef long long ll;
typedef std::pair<int, int> pii;
int T, n;
struct Pair {
int x, y, sum;
friend bool operator < (Pair p1, Pair p2) {
if (p1.sum != p2.sum) return p1.sum < p2.sum;
return std::min(p1.x, p1.y) < std::min(p2.x, p2.y);
}
}p[N];
int main() {
scanf("%d", &T);
while (T--) {
scanf("%d", &n);
for (int i = 1; i <= n; ++i) {
scanf("%d %d", &p[i].x, &p[i].y);
p[i].sum = p[i].x + p[i].y;
}
std::sort(p + 1, p + n + 1);
for (int i = 1; i <= n; ++i) printf("%d %d ", p[i].x, p[i].y);
puts("");
}
return 0;
}
D. Skipping
Problem
Sol&Code
发现答案最后一定是对于题目集的一段前缀减去跳过的题目。
于是考虑维护跳到题目 \(i\) 最少跳过多少分,对于 \(1\) 来说是 \(0\)。按照跳到 \(i\) 最少跳过的分数加上 \(i\) 的分数从小到大去更新更大的 \(i\)。用大根堆来做。
#include <bits/stdc++.h>
#define M 10001
#define N 400001
#define inf 100000000000000007
typedef long long ll;
typedef std::pair<ll, ll> pll;
bool used[N];
ll sum[N], skip[N];
int T, n, a[N], b[N];
std::priority_queue<pll> q;
int main() {
scanf("%d", &T);
while (T--) {
scanf("%d", &n);
for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
for (int i = 1; i <= n; ++i) scanf("%d", &b[i]);
for (int i = 1; i <= n; ++i) sum[i] = sum[i - 1] + a[i];
for (int i = 1; i <= n; ++i) skip[i] = inf, used[i] = 0;
skip[1] = 0;
int nowp = 2;
q.push({0 - a[1], 1});
while (!q.empty()) {
auto [x, y] = q.top();
q.pop(); x = -x;
if (b[y] <= y) continue;
if (used[y]) continue;
used[y] = true;
for (int i = std::max((int)y + 1, nowp); i <= b[y]; ++i) {
skip[i] = std::min(skip[i], (ll)x);
q.push({0 - a[i] - skip[i], i});
}
nowp = std::max(nowp, b[y] + 1);
}
long long ans = -inf;
for (int i = n; i >= 1; --i) ans = std::max(ans, sum[i] - skip[i]);
printf("%lld\n", ans);
}
return 0;
}
After
唉唉,掉大分了。