Educational Codeforces Round 96 (Rated for Div. 2) ABCEDF
A
暴力拼
int main(){
IOS;
for (cin >> _; _; --_) {
cin >> n;
bool f = false;
rep (i, 0, n / 3) {
if (f) break;
rep (j, 0, n / 5)
if ((n - i * 3 - j * 5) % 7 == 0) {
cout << i << ' ' << j << ' ' << (n - i * 3 - j * 5) / 7 << '\n';
f = true;
break;
}
}
if(!f) cout << -1 << '\n';
}
return 0;
}
B
排序选就完了
int main() {
IOS;
for (cin >> _; _; --_) {
cin >> n >> k; ++k;
ll ans = 0;
rep (i ,1, n) cin >> a[i];
sort(a + 1, a + 1 + n);
rep (i, 1, k) ans += a[n - i + 1];
cout << ans << '\n';
}
return 0;
}
C
倒着输出完事, 必定为2
int main() {
IOS;
for (cin >> _; _; --_) {
cin >> n; m = n; k = n - 1;
cout << 2 << '\n';
rep (i, 2, n) {
cout << k << ' ' << m << '\n';
m = (k + m + 1) / 2; --k;
}
}
return 0;
}
D
贪心, 统计0110101串个数 cnt
为 0 的时候 遇见连续的 0000 或 1111 你只能 +1
有 cnt 的时候 你就可以慢悠悠的 取 连续串, 取的时候留一个, 相当于又多了个 01
int main() {
IOS;
for (cin >> _; _; --_) {
cin >> n >> s + 1;
int ans = 0, c = 0;
rep (i, 1, n) {
int j = i;
while (j + 1 <= n && s[j] == s[j + 1]) ++j;
if (i == j) ++c;
else {
if (c >= j - i) ans += j - i, c -= j - i - 1;
else ans += c + 1, c = 0;
i = j;
}
}
ans += c + 1 >> 1;
cout << ans << '\n';
}
return 0;
}
E
求逆序对
看题目, 相邻交换, 最后有序, (逆序对即使交换的最少次数, 归并排序交换的次数)
int n, m, _, k;
char s[N];
int a[N], c[N];
void add(int x, int k) {
for (; x <= n; x += -x & x) c[x] += k;
}
int ask(int x) {
int ans = 0;
for (; x; x -= -x & x) ans += c[x];
return ans;
}
int main() {
IOS; cin >> n >> s + 1;
VI tax[27]; ll ans = 0;
per(i, n, 1) tax[s[i] ^ 96].pb(n - i + 1);
per(i, n, 1) a[i] = tax[s[i] ^ 96].back(), tax[s[i] ^ 96].pop_back();
rep (i, 1, n) add(a[i], 1), ans += i - ask(a[i]);
cout << ans;
return 0;
}
F
没一眼看出来E是逆序对是真的....
一看提, 贪心的想把每波怪 在来之前最少需要多少f[i]子弹算出来
然而, 你算出来当前贪心最少需要多少子弹, 然后你当前打光了子弹, 下一波 f[i + 1] > 0 直接 gg
所以我们要考虑后效性, 倒着想, f[i] 表示 i ~ n 在第i波之前需要最少的子弹
这样就没后效性了, 求晚 f[i], 正着来一遍就好了
但是! 我们有 r[i] == l[i + 1] 的情况
我们能直接将 i 和 i + 1 合并吗? 显然不能(i + 1 波怪 可以在 r[i + 1]之前打完, i波不行)
但是 f[i + 1] 和 f[i] 可以啊, i 和 i + 1之间不能换弹, 所以 f[i]必须包含 f[i + 1] 的部分, 这样就处理完了
(你可以直接将 f[i] += f[i + 1], 在特判 -1, 也可以直接 a[i] += f[i + 1])
ll a[N], l[N], r[N], f[N];
int main() {
IOS; cin >> n >> k;
ll ans = 0, res = k;
rep (i, 1, n) cin >> l[i] >> r[i] >> a[i];
per (i, n, 1) {
ll res = a[i];
if (r[i] == l[i + 1]) res += f[i + 1];
if (res > (r[i] - l[i] + 1) * k) { cout << -1; return 0; }
f[i] = max(0ll, res - (r[i] - l[i]) * k);
}
rep (i, 1, n) {
if (res < f[i]) ans += res, res = k;
ans += a[i]; res = ((res - a[i]) % k + k) % k;
}
cout << ans;
return 0;
}