ABC 440
Table of Contents
https://atcoder.jp/contests/abc440
A. Octave
https://atcoder.jp/contests/abc440/tasks/abc440_a
void solve() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
ll X, Y;
cin >> X >> Y;
cout << X * (1ll << Y) << endl;
}
B. Trifecta
https://atcoder.jp/contests/abc440/tasks/abc440_b
void solve() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
ll N;
cin >> N;
vector<pair<ll, ll>> times;
rep(i, N) {
ll t;
cin >> t;
times.push_back({t, i + 1});
}
sort(all(times));
vll ans;
rep(i, 3) {
ans.push_back(times[i].second);
}
print(ans);
}
C. Striped Horse
https://atcoder.jp/contests/abc440/tasks/abc440_c
コンテスト中には解けなかったが自力で解けた。
周期 $2W$ ごとに $W$ 個のコストを足す区間と、$W$ 個のコストを飛ばす区間が交互に現れる。 ここで区間は右開区間として考える。 採用する区間のうち一番左にある区間の右端の位置を $r$ とすると $[r-W, r)$, $[r+W, r+2W)$, … の区間を採用することになる。 ここで $r \in [1, 2W]$ である。
$r$ の取り方が $2W$ 通りしかないので、loop の回数は $\frac{N}{2W}$ であるので累積和を計算しておけば $O(N)$ で解ける。
下記のコードは簡単のために $C$ の長さを $N + 2W$ に拡張しているので計算量は $O(N+W)$ である。
template <typename T>
struct Cumsum {
vector<T> data;
Cumsum(vector<T> v) {
int n = v.size();
data.resize(n + 1);
data[0] = 1;
rep(i, n) {
data[i + 1] = data[i] + v[i];
}
}
// sum of range [l,r)
ll sum(int l, int r) {
return data[r] - data[l];
}
};
void solve() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
auto cal = []() -> void {
ll N, W;
cin >> N >> W;
vll C(N + W * 2);
rep(i, N) cin >> C[i];
N += W * 2;
Cumsum cm(C);
ll ans = INF;
rep2(fin, 1, W * 2 + 1) {
ll tmp = 0;
for (ll r = fin; r < N; r += W * 2) {
tmp += cm.sum(max(0ll, r - W), r);
}
chmin(ans, tmp);
}
cout << ans << endl;
};
int t;
cin >> t;
rep(i, t) cal();
}
解説放送で知ったやり方。 $2W$ 離れたところは一蓮托生なので $2W$ 個の要素の配列から $W$ 個の連続する要素を選ぶ問題に帰着できる。
void solve() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
auto cal = []() -> void {
ll N, W;
cin >> N >> W;
vll C(W * 4);
rep(i, N) {
ll c;
cin >> c;
C[i % (W * 2)] += c;
C[i % (W * 2) + W * 2] += c;
}
ll ans = accumulate(C.begin(), C.begin() + W, 0ll);
ll sum = ans;
rep2(i, 1, W * 2 + 1) {
sum -= C[i - 1];
sum += C[i + W - 1];
chmin(ans, sum);
}
cout << ans << endl;
};
int t;
cin >> t;
rep(i, t) cal();
}
D. Forbidden List 2
https://atcoder.jp/contests/abc440/tasks/abc440_d
コンテスト中には解けなかったが自力で解けた。
$x \geq X_j$ とする。$[X_j, x]$ の区間に含まれる $A_i$ の個数を $n$ とすると $x$ は $X_j$ から $A$ に含まれない数の $x - X_j + 1 - n$ 番目の数である。
$x$ を二分探索で動かして $Y_j$ 番目の数を求めればよい。
void solve() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
ll N, Q;
cin >> N >> Q;
vll A(N);
rep(i, N) cin >> A[i];
sort(all(A));
rep(i, Q) {
ll x, y;
cin >> x >> y;
auto lit = lower_bound(all(A), x);
ll ac = 1ll << 60, wa = x - 1;
while (ac - wa > 1) {
ll wj = (ac + wa) / 2;
auto rit = upper_bound(lit, A.end(), wj);
ll num = rit - lit;
if (wj - x + 1 - num < y) {
wa = wj;
} else {
ac = wj;
}
}
cout << ac << endl;
}
}
E. Cookies
https://atcoder.jp/contests/abc440/tasks/abc440_e
F. Egoism
https://atcoder.jp/contests/abc440/tasks/abc440_f