Codeforces Round #657 (Div. 2) 感想
問題
Dashboard - Codeforces Round #657 (Div. 2) - Codeforces
感想
2完。むっっっっっず! 今回、writerの威圧感がすごかったから嫌な予感はしてたんだよな~~~。 でもCは解けるべき問題だった。くやしい。。。
レート変動は 1932 -> 1900 でギリギリ紫を守れた。いよいよ次回Div.1。たのしみ~~。
A - Acacius and String
3分で解いてやるぜ~~wwと意気込んでいたら全然解けなくてめちゃくちゃ焦った。
最初、"exactly once" を読み飛ばしていて(太字を読み飛ばすな) 「"abacaba"にできるか前から確認すればいいだけやん楽勝!」と言いながら実装するものの、もちろんサンプルが合わず??となった。
そして、問題文に "exactly once" と書いてあることを発見し、冷や汗をかく。
ここで、やべ~~と思いながらDashboardを見るとまだ200人くらいしかACしてなくてちょっと安心する。
しかし、そこから30分くらい迷走してしまい、絶望する。
結局、] を "abacaba" にできるかを確認し、できるときに 全体に "abacaba" が連続部分列として何回登場するかをカウントし、 それがちょうど 1 になるかを確かめるだけでよかった。"abacaba" にする部分以外の ? は適当に z とかで埋めとけばいい。
いつもに比べてあまりにも解かれていなかったため、変に難しく考えてしまった。反省。。。
リンク: http://codeforces.com/contest/1379/submission/87307205提出コード
void solve() {
int Q;
cin >> Q;
const string target = "abacaba";
while (Q--) {
ll N;
cin >> N;
string S;
cin >> S;
bool ok = false;
for (ll i = 0; i < N; i++) {
if (i + 7 > N) continue;
string S_cpy = S;
bool good = true;
for (ll j = 0; j < 7; j++) {
if (S_cpy[i + j] != '?' && S_cpy[i + j] != target[j]) {
good = false;
break;
}
}
if (good) {
for (ll j = 0; j < 7; j++) {
if (S_cpy[i + j] == '?') {
S_cpy[i + j] = target[j];
}
}
ll cnt = 0;
for (ll j = 0; j < N; j++) {
if (j + 7 > N) continue;
bool fg = true;
for (ll k = 0; k < 7; k++) {
if (S_cpy[j + k] != target[k]) {
fg = false;
break;
}
}
if (fg) {
++cnt;
}
}
if (cnt > 1) {
good = false;
}
}
if (good) {
ok = true;
S = S_cpy;
break;
}
}
for (ll i = 0; i < N; i++) {
if (S[i] == '?') {
S[i] = 'z';
}
}
if (ok) {
cout << "Yes\n";
cout << S << "\n";
}
else {
cout << "No\n";
}
}
}
B - Dubious Cyrpto
Aでの失敗に動揺してしまい、Bでもあたふたして時間を消費してしまった。メンタルさん......
でも、この問題も Div.2-B にしてはむずかしいよね。
とおくと、 となるから 。また、。
を固定して考える。
] は 0 について対称な区間であることに注目すると、 としたとき、 の候補として考えるのは または のみでいいことが分かる(この2つのいずれかが最も0に近い)。
を または と定めて を満たすか確認し、満たされていれば をその値で確定する。
ただし、 とするときは確認すべき条件がもう一つあって、「n は正整数」なので、 であることも確認する必要がある。
が確定できれば と は適当な方法(僕は全探索をした)で決定できる。
上を を から まで動かしながら、 が確定できるまで続ける。
むずかしすぎる。
これを ABC で出したときに diff がどうなるか気になる。
リンク:http://codeforces.com/contest/1379/submission/87326619提出コード
void solve() {
int Q;
cin >> Q;
while (Q--) {
ll L, R, M;
cin >> L >> R >> M;
ll a, b, c;
ll d;
for (ll x = L; x <= R; x++) {
ll q = M / x;
ll r = M % x;
// d > 0
if (q >= 1) {
if (r >= L - R && r <= R - L) {
a = x;
d = r;
break;
}
}
// d < 0
r = r - x;
if (r >= L - R && r <= R - L) {
a = x;
d = r;
break;
}
}
for (ll x = L; x <= R; x++) {
ll y = x + d;
if (y >= L && y <= R) {
b = y;
c = x;
}
}
cout << a << " " << b << " " << c << "\n";
}
}
C - Choosing flowers
解けなかった。「1本だけ購入する花の種類数」を固定して考えてしまい、沼にはまった。
コンテスト後によく考えると、2本以上購入する花は 0 または 1 種類だけだと考えていい *1 ので、「2本以上購入することを許す花」を固定して考えると良いことに気づいた。
番目の花を2本以上購入することを許すときの満足度の最大値を求める。
番目の花を 本購入する状態から考え始める。もし、 となる が存在するなら 番目の花の購入数を 1 減らし、 番目の花の購入数を1増やすべきである。なので結局、 である花をすべて、番目の花を1つ犠牲にして1本ずつ購入するのが最適である。
この最適解は二分探索で で求められる。これをすべての ] について求め、それらの max を答えとすればいい。計算量は全部で 。
う~~ん、、これは落ち着いていれば解けたんじゃないかな。。。
リンク:http://codeforces.com/contest/1379/submission/87344635コンテスト後提出コード
void solve() {
int Q;
cin >> Q;
vector<Pll> flws;
Vl cuma;
while (Q--) {
ll N, M;
cin >> N >> M;
flws.resize(M);
for (ll i = 0; i < M; i++) {
int a, b;
cin >> a >> b;
flws[i] = {a, b};
}
sort(flws.begin(), flws.end(), greater<Pll>());
cuma.assign(M + 1, 0);
for (ll i = 0; i < M; i++) {
cuma[i + 1] = cuma[i] + flws[i].first;
}
ll ans = 0;
for (ll i = 0; i < M; i++) {
auto [ai, bi] = flws[i];
ll left = -1, right = M;
while (right - left > 1) {
ll mid = (left + right) >> 1;
if (bi < flws[mid].first) {
left = mid;
}
else {
right = mid;
}
}
if (right >= N) {
continue;
}
ll t;
if (i < right) {
t = cuma[right] + bi * (N - right);
}
else {
t = cuma[right] + ai + bi * (N - right - 1);
}
ans = max(ans, t);
}
if (N <= M) {
ans = max(ans, cuma[N]);
}
cout << ans << "\n";
}
}
D以降
見てないので割愛。
*1:2本以上購入する花が2種類以上あるとき、 が最大である花の購入数を 1 増やし、その他の花の購入数を 1 減らすことにしても Vladimir の妻の満足度は減らない。