Idea: BledDest
Tutorial
Tutorial is loading...
Solution (BledDest)
t = int(input())
for i in range(t):
n, k = map(int, input().split())
ans = 0
if n % 2 == 1:
n -= k
ans = 1
k -= 1
ans += (n + k - 1) // k
print(ans)
Idea: BledDest
Tutorial
Tutorial is loading...
Solution (Neon)
#include <bits/stdc++.h>
using namespace std;
int main() {
int t;
cin >> t;
while (t--) {
int n, k;
cin >> n >> k;
vector<int> a(n);
for (auto &x : a) cin >> x;
long long ans = 0;
if (k > 1) {
sort(a.begin(), a.end(), greater<int>());
ans = accumulate(a.begin(), a.begin() + k + 1, 0LL);
} else {
int l = *max_element(a.begin(), a.end() - 1);
int r = *max_element(a.begin() + 1, a.end());
ans = max(l + a.back(), r + a[0]);
}
cout << ans << '\n';
}
}
Idea: fcspartakm
Tutorial
Tutorial is loading...
Solution (awoo)
from bisect import bisect_left
for _ in range(int(input())):
n, m = map(int, input().split())
a = sorted(list(map(int, input().split())))
ans = 0
for k in range(1, n):
x = m - bisect_left(a, k)
y = m - bisect_left(a, n - k)
ans += x * y - min(x, y)
print(ans)
Idea: BledDest
Tutorial
Tutorial is loading...
Solution (Neon)
#include <bits/stdc++.h>
using namespace std;
using li = long long;
const int B = 60;
const li INF = 1e18;
int main() {
ios::sync_with_stdio(false); cin.tie(0);
array<array<li, B>, B> dp;
for (int i = 0; i < B; ++i) {
for (int j = 0; j < B; ++j) {
dp[i][j] = INF;
}
}
dp[0][0] = 0;
for (int x = 0; x < B; ++x) {
for (int i = B - 1; i >= 0; --i) {
for (int j = B - 1; j >= 0; --j) {
if (dp[i][j] == INF) continue;
if (i + x < B) dp[i + x][j] = min(dp[i + x][j], dp[i][j] + (1LL << x));
if (j + x < B) dp[i][j + x] = min(dp[i][j + x], dp[i][j] + (1LL << x));
}
}
}
int t;
cin >> t;
while (t--) {
li x, y;
cin >> x >> y;
li ans = INF;
for (int i = 0; i < B; ++i) {
for (int j = 0; j < B; ++j) {
if ((x >> i) == (y >> j)) ans = min(ans, dp[i][j]);
}
}
cout << ans << '\n';
}
}
Idea: BledDest
Tutorial
Tutorial is loading...
Solution (BledDest)
#include <bits/stdc++.h>
using namespace std;
const int MOD = 998244353;
const int K = 31;
int add(int x, int y)
{
x += y;
while(x >= MOD) x -= MOD;
while(x < 0) x += MOD;
return x;
}
int sub(int x, int y)
{
return add(x, -y);
}
int mul(int x, int y)
{
return (x * 1ll * y) % MOD;
}
int binpow(int x, int y)
{
int z = 1;
while(y)
{
if(y & 1) z = mul(z, x);
x = mul(x, x);
y >>= 1;
}
return z;
}
int dp[K][2][2][2];
int choose2(int n)
{
return mul(n, mul(sub(n, 1), binpow(2, MOD - 2)));
}
void solve()
{
int n, m, A, B;
cin >> n >> m >> A >> B;
memset(dp, 0, sizeof dp);
dp[0][0][0][0] = 1;
for(int i = 0; i + 1 < K; i++)
for(int f1 = 0; f1 <= 1; f1++)
for(int f2 = 0; f2 <= 1; f2++)
for(int fx = 0; fx <= 1; fx++)
{
int d = dp[i][f1][f2][fx];
if(!d) continue;
int j = K - 2 - i;
int curA = (A >> j) & 1;
int curB = (B >> j) & 1;
for(int bit_a = 0; bit_a <= 1; bit_a++)
for(int bit_b = 0; bit_b <= 1; bit_b++)
for(int bit_x = 0; bit_x <= 1; bit_x++)
{
if(f1 == 0 && bit_a == 1 && curA == 0) continue;
if(f2 == 0 && bit_b == 1 && curB == 0) continue;
if(fx == 0 && bit_x == 1 && (bit_a == 0 || bit_b == 0)) continue;
int nf1 = max(f1, bit_a ^ curA);
int nf2 = max(f2, bit_b ^ curB);
int nfx = max(fx, bit_x);
int& d2 = dp[i + 1][nf1][nf2][nfx];
d2 = add(d2, d);
}
}
int pairs_of_pairs = 0;
for(int i = 0; i <= 1; i++)
for(int j = 0; j <= 1; j++)
pairs_of_pairs = add(pairs_of_pairs, dp[K - 1][i][j][1]);
int comb_a = sub(binpow(2, n), 2);
int comb_b = sub(binpow(2, m), 2);
int ans = mul(pairs_of_pairs, mul(comb_a, comb_b));
ans = add(ans, mul(add(A, 1), add(B, 1)));
ans = add(ans, mul(add(A, 1), mul(comb_b, choose2(add(B, 1)))));
ans = add(ans, mul(add(B, 1), mul(comb_a, choose2(add(A, 1)))));
cout << ans << endl;
}
int main()
{
int t;
cin >> t;
for(int i = 0; i < t; i++) solve();
}
2075F - Beautiful Sequence Returns
Idea: adedalic
Tutorial
Tutorial is loading...
Solution (adedalic)
#include<bits/stdc++.h>
using namespace std;
#define fore(i, l, r) for(int i = int(l); i < int(r); i++)
#define sz(a) int((a).size())
typedef long long li;
typedef pair<int, int> pt;
const int INF = int(1e9);
const li INF64 = li(1e18);
vector<int> Tadd, Tmax;
int getmax(int v) {
return Tmax[v] + Tadd[v];
}
void push(int v) {
Tadd[2 * v + 1] += Tadd[v];
Tadd[2 * v + 2] += Tadd[v];
Tadd[v] = 0;
}
void upd(int v) {
Tmax[v] = max(getmax(2 * v + 1), getmax(2 * v + 2));
}
void addVal(int v, int l, int r, int lf, int rg, int val) {
if (l == lf && r == rg) {
Tadd[v] += val;
return;
}
push(v);
int mid = (l + r) >> 1;
if (lf < mid)
addVal(2 * v + 1, l, mid, lf, min(mid, rg), val);
if (rg > mid)
addVal(2 * v + 2, mid, r, max(lf, mid), rg, val);
upd(v);
}
int n;
vector<int> a;
inline bool read() {
if(!(cin >> n))
return false;
a.resize(n);
fore (i, 0, n)
cin >> a[i];
return true;
}
inline void solve() {
vector<int> ask(n, 0);
int mx = -1;
for (int i = n - 1; i >= 0; i--) {
if (a[i] > mx) {
ask[i] = 1;
mx = a[i];
}
}
vector<int> left;
fore (i, 0, n) {
if (left.empty() || a[left.back()] > a[i])
left.push_back(i);
}
vector<pt> seg(n);
fore (i, 0, n) {
int lf = upper_bound(left.begin(), left.end(), i, [&left](int v, int i) {
return a[v] > a[i];
}) - left.begin();
int rg = lower_bound(left.begin(), left.end(), i) - left.begin();
seg[i] = {lf, rg};
}
Tadd.assign(4 * n, 0);
Tmax.assign(4 * n, 0);
vector<int> ordToAdd(n);
iota(ordToAdd.begin(), ordToAdd.end(), 0);
sort(ordToAdd.begin(), ordToAdd.end(), [](int i, int j) {
return a[i] < a[j];
});
auto addToSeg = [&left, &seg](int id, int val) {
auto [lf, rg] = seg[id];
if (lf < rg)
addVal(0, 0, sz(left), lf, rg, val);
};
int ans = 0;
int pos = 0;
vector<int> added(n, 0);
for (int i = n - 1; i >= 0; i--) {
while (pos < n && a[ordToAdd[pos]] < a[i]) {
if (ordToAdd[pos] <= i) {
addToSeg(ordToAdd[pos], 1);
added[ordToAdd[pos]] = 1;
}
pos++;
}
if (ask[i]) {
auto [lf, rg] = seg[i];
ans = max(ans, 1 + (lf < rg ? 1 + getmax(0) : 0));
}
if (added[i]) {
addToSeg(i, -1);
added[i] = 0;
}
}
cout << ans << endl;
}
int main() {
#ifdef _DEBUG
freopen("input.txt", "r", stdin);
int tt = clock();
#endif
ios_base::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
cout << fixed << setprecision(15);
int t; cin >> t;
while(t--) {
(read());
solve();
#ifdef _DEBUG
cerr << "TIME = " << clock() - tt << endl;
tt = clock();
#endif
}
return 0;
}
It's a good thing that you remember to share the Editorial!
Thanks! The tasks were really interesting!
Nice~~~
Can anyone share the approach to problem C's solution using suffix array? Btw, thanks for the editorial, really helpful!
f
No rating rollback? There are clear cheaters in top 100
give them some time eventually they are skipped (at least most of them)
Here is a clean implementation of task C, if anyone is interested in taking a look.
For problem C, there is also an $$$O(m \log m)$$$ solution (example: 311315934) which is what I did during the contest, arguably overengineering the solution.
The essential idea is that if you have two paints with indices $$$i$$$ and $$$j$$$, then you can use them to paint the fence only if $$$a_i + a_j ≥ n$$$, and if you clip the values of $$$a$$$ to $$$n - 1$$$ (because you can never paint more than $$$n - 1$$$ boards with a single color) then the number of ways to paint the fence with these two colors is $$$a_i + a_j - n + 1$$$.
That gives a trivial $$$O(m^2)$$$ solution where we consider all possible pairs of $$$i$$$ and $$$j$$$, but of course that is too slow. But we can improve this by first sorting the array $$$a$$$, then for each index $$$j$$$ you can calculate the first index $$$i < j$$$ such that $$$a_i + a_j ≥ n$$$, and the number of ways to paint the fence such that the right half is painted with index $$$j$$$ is $$$\sum_{k=i}^j a_k + a_j - n + 1$$$ (in my code, the result of this sum is stored in
acc
).As $$$j$$$ increases, $$$i$$$ decreases. We can update the sum (
acc
) as we incrementj
and add new values of $$$i$$$ as they become available. Since in this we assume $$$k < j$$$ we are only counting half of the solutions, so we need to multiply the result by $$$2$$$ to obtain the final answer.The main algorithm runs in $$$O(m)$$$ time, but since this requires sorting the array $$$a$$$ first, it's technically $$$O(m \log m)$$$.
I also used the same approach..
D actually doesn't require DP, and can be solved if x,y are given as binary strings of length <= 2e5.
Say we have to remove last p bits of x and last q bits of y.
For now suppose p,q are atleast 3, let r be the smallest number such that r(r+1)/2 >= p+q.
I claim the optimal way to select the numbers for the operations are 1,....r and remove r(r+1)/2-(p+q) incase p+q != r(r+1)/2.
This is clearly the minimum as we'd like to minimize the maximum number we take which will be r, and further we'd like to remove the largest possible number, if we take all numbers from 1 to r.
I didn't explicitly prove we can split them to obtain (p,q) , but it can probably proved by induction, however it fails if min(p,q) is 1 or 2 so we have to add some extra checks when min(p,q) is 0,1 or 2.
You can refer to https://codeforces.me/contest/2075/submission/311165732 for those edge cases.
Alternate solution for E: everything before $$$a_1 \oplus a_2 = b_1 \oplus b_2$$$ is the same. Now, let $$$g(n, m)$$$ denote the number of pairs $$$(i, j)$$$ such that $$$0 \le i < j \le n$$$ and $$$i \oplus j = m$$$.
First, I claim that $$$g(n, m) = g(n, 2^k)$$$ where $$$k$$$ is largest integer with $$$2^k \le m$$$. This is because $$$j \oplus 2^k < j \iff j \oplus m < j$$$, i.e. any number $$$j$$$ that can be xorred with $$$2^k$$$ can be xorred with $$$m$$$ and vice versa.
This already means that the number of quadruplets $$$(a_1, a_2, b_1, b_2)$$$ is $$$\sum_{k=0}^{\log \max} 2^k g(A, 2^k) g(B, 2^k)$$$, where a factor of $$$2^k$$$ comes from the fact that there are $$$2^k$$$ values of $$$m$$$ with this $$$k$$$.
All that remains is quickly evaluating $$$g(n, 2^k)$$$. This is simply the count of integers from $$$0$$$ to $$$n$$$ with $$$k$$$-th bit set because any number with the $$$k$$$-th bit on has a pair, and every pair contains exactly one number with the $$$k$$$-th bit on.
For C, can someone confirm that the following is an O(n+m) solution -- Suppose I create an array $$$cnt[]$$$ such that $$$cnt[j]$$$ denotes the number of paints that can paint at least $$$j$$$ fences (this can be done in O(n) time). Now I create another array sol[] such that
then sol[i] denotes the number of solutions to the equation
where
This can also be done in O(n) time. Then, the answer is just the sum
subtracting (2*a[i]-n+1) whenever 2*a[i]>=n (to account for x_1 and x_2 representing the same colour).