Codeforces Round #783 (Div. 2)
Codeforces Round #783 (Div. 2)
A - Direction Change
保證讓\(n \geq m\), 只要\(m > 1\) 在第二維上就可以反覆橫跳,則必定有解
int main() { IOS; for (cin >> _; _; --_) { cin >> n >> m; if (m > n) swap(n, m); if (n - m > 1 && m < 2) cout << -1 << '\n'; else if (n - m < 2) cout << n + m - 2 << '\n'; else if (n - m & 1) cout << 2 * n - 3 << '\n'; else cout << 2 * n - 2 << '\n'; } return 0; }
B - Social Distance
先拆環
假設最後一個人坐在最後一個位置,則第一人必定坐在\(max(a_n, a_1) + 1\)的位置上,這樣才能保證兩人在換上相隔人數合法,
之後下一個人的位置\(s_i = s_{i - 1} + max(a_{i -1}, a_i) + 1\),只要保證最後一個人位置不超過拆環的序列長度即可,
假定$a_0 = a_n, b_i = max(a_{i - 1}, a_i) $
然後就是貪心,使得兩人之間所需空位差距儘量最小,排個序即可
int main() { IOS; for (cin >> _; _; --_) { cin >> n >> m; bool f = 1; for (int i = 1; i <= n; ++i) cin >> a[i]; sort(a + 1, a + 1 + n); a[0] = a[n]; for (int i = 1; i <= n; ++i) b[i] = max(a[i], a[i - 1]); for (int i = 1, j = 0; i <= n && f; ++i) { j += b[i] + 1; if (j > m) f = 0; } cout << (f ? "YES" : "NO") << '\n'; } return 0; }
C - Make it Increasing
模擬題意暴力即可,必定存在一個位置\(i\)不用操作,且其前面的數都要進行 減 操作,其後面的數都需要 加 操作,
暴力去列舉這個\(i\)即可
int main() { IOS; cin >> n; for (int i = 1; i <= n; ++i) cin >> a[i]; long long mx = 2e18; for (int i = 1; i <= n; ++i) { long long cur = 0, ls = 0; for (int j = i - 1; j; --j) { long long c = ls / a[j] + 1; cur += c; ls = a[j] * c; } ls = 0; for (int j = i + 1; j <= n; ++j) { long long c = ls / a[j] + 1; cur += c; ls = a[j] * c; } umin(mx, cur); } cout << mx; return 0; }
D - Optimal Partition
dp, \(f_i\) 表示以\(i\)結尾分割後的最大值,則
\(f_i = \left\{\begin{matrix} max(f_j + i - j)& \sum_{k = 1}^i a_k > \sum_{k = 1}^j a_k\\ max(f_j) & \sum_{k = 1}^i a_k = \sum_{k = 1}^j a_k\\ max(f_j - i + j) & \sum_{k = 1}^i a_k < \sum_{k = 1}^j a_k \end{matrix}\right. \quad i > j \geq 0\)
即
\(\left\{\begin{matrix} f_i - i = max(f_j - j)& \sum_{k = 1}^i a_k > \sum_{k = 1}^j a_k\\ f_i = max(f_j) & \sum_{k = 1}^i a_k = \sum_{k = 1}^j a_k\\ f_i + i= max(f_j + j) & \sum_{k = 1}^i a_k < \sum_{k = 1}^j a_k \end{matrix}\right. \quad i > j \geq 0\)
一維偏序用for迴圈搞定,對於字首和的偏序可以通過數軸對映,離散化在數軸上表示字首和
再隨便找資料結構維護數軸上的 \(f_i - i, f_i, f_i + i\) 的區間最值資訊即可
本人選擇線段樹,一棵即能維護這三種資訊在區間最值的資訊
const int N = 5e5 + 5;
struct BIT {
struct node {
int l, r, val[3];
} tr[N << 2];
void build(int p, int l, int r) {
tr[p] = {l, r, {-1000000, -1000000, -1000000}};
if (l == r) return;
int mid = l + r >> 1;
build(p << 1, l, mid); build(p << 1 | 1, mid + 1, r);
}
void change(int p, int k, int v, int id) {
if (tr[p].l == k && tr[p].r == k) {
umax(tr[p].val[0], v - id);
umax(tr[p].val[1], v);
umax(tr[p].val[2], v + id);
return;
}
int mid = tr[p].l + tr[p].r >> 1;
if (mid >= k) change(p << 1, k, v, id);
else change(p << 1 | 1, k, v, id);
rep(i, 0, 2) umax(tr[p].val[i], max(tr[p << 1].val[i], tr[p << 1 | 1].val[i]));
}
int ask(int p, int l, int r, int k) {
if (tr[p].l >= l && tr[p].r <= r) return tr[p].val[k];
int mid = tr[p].l + tr[p].r >> 1;
if (mid >= r) return ask(p << 1, l, r, k);
else if (mid < l) return ask(p << 1 | 1, l, r, k);
return max(ask(p << 1, l, r, k), ask(p << 1 | 1, l, r, k));
}
} bit;
int n, m, _, k, cas;
long long a[N], b[N];
int main() {
IOS;
for (cin >> _; _; --_) {
cin >> n;
vector<long long> c(1, 0);
for (int i = 1; i <= n; ++i)
cin >> a[i], c.emplace_back(a[i] += a[i - 1]);
sort(all(c)); c.erase(unique(all(c)), c.end());
m = c.size();
for (int i = 1; i <= n; ++i) b[i] = lower_bound(all(c), a[i]) - c.begin() + 1;
bit.build(1, 1, m);
int cur;
bit.change(1, lower_bound(all(c), 0) - c.begin() + 1, 0, 0);
for (int i = 1, ls = 0; i <= n; ++i, ls = cur) {
cur = (a[i] - a[i - 1] > 0 ? 1 : a[i] - a[i - 1] < 0 ? -1 : 0) + ls;
long long t = bit.ask(1, b[i], b[i], 1);
umax(cur, bit.ask(1, b[i], b[i], 1));
if (b[i] > 1) umax(cur, bit.ask(1, 1, b[i] - 1, 0) + i);
if (b[i] < m) umax(cur, bit.ask(1, b[i] + 1, m, 2) - i);
bit.change(1, b[i], cur, i);
}
cout << cur << '\n';
}
return 0;
}
E - Half Queen Cover
不考慮斜著。則就是\(n\)個半皇后佔據\(n\)行\(n\)列,考慮斜著,也就是\(k\)個半皇后形成的對角線正好拼成了一g個\((n - k) \times (n - k)\)的矩形
如圖,\(k = 7\) 半皇后用行列覆蓋了\(k \times k\)矩形,並額外還覆蓋到了肉色的兩個矩形,並通過\(n - k\)條對角線覆蓋了\((n - k) \times (n - k)\)的矩形
邊長為\(n - k\)的正方形有\((n - k) * 2 - 1\) 條對角線,則 \(k \geq 2 \times n - 2 \times k - 1\)
則 \(k = \left \lceil \frac{2n - 1}{3} \right \rceil\), 之後就是構造\(k\)個半皇后覆蓋\(k * k\)矩形的問題
int main() {
IOS;
cin >> n; m = (2 * n + 1) / 3;
cout << m << '\n';
for (int i = 1, j = 1; i <= m; ++i, j += 2) {
if (j > m) j = 2;
cout << i << ' ' << j << '\n';
}
return 0;
}