ограничение по времени на тест2 секунды ограничени...
Criado em: 21 de abril de 2026
Criado em: 21 de abril de 2026
ограничение по времени на тест2 секунды
ограничение по памяти на тест512 мегабайт
Назовем строку t
чередующейся, если для любого i
от 1
до n−1
выполняется ti≠ti+1
.
Дана строка s
, которая состоит только из букв «a» и/или «b». Вы можете не более одного раза совершить с ней следующую операцию:
выбрать подстроку slsl+1…sr
, состоящую хотя бы из одного символа;
после выбора подстроки можно изменить в ней все буквы, то есть заменить все «a» на «b» и все «b» на «a» (вы можете это сделать, но не обязаны);
перевернуть выбранную подстроку, то есть превратить строку s1s2…sl−1slsl+1…srsr+1…sn
в s1s2…sl−1srsr−1…slsr+1…sn
.
Обратите внимание, что вы не обязаны выполнять второй пункт операции. Например, для строки s=
«ababbab» после одной операции можно получить «abababa», выбрав в операции подстроку s5s6s7
и выполнив второй пункт операции, или «bababab», выбрав подстроку s1s2s3s4
и не выполнив второй пункт операции. Однако третий пункт операции выполняется всегда.
Можно ли получить из строки s
чередующуюся строку?
Входные данные
Каждый тест состоит из нескольких наборов входных данных. В первой строке находится одно целое число t
(1≤t≤104
) — количество наборов входных данных. Далее следует описание наборов входных данных.
В единственной строке каждого набора входных данных содержится строка s
(2≤|s|≤2⋅105
). Строка состоит только из строчных латинских букв «a» и/или «b».
Дополнительные ограничения на входные данные:
сумма длин строк по всем наборам входных данных не превосходит 2⋅105
.
Выходные данные
Для каждого набора входных данных выведите одно из двух:
YES, если возможно получить чередующуюся строку из s
;
NO в противном случае.
Каждую букву можно выводить в любом регистре.
Пример
Входные данныеСкопировать
8
abbaba
aaaaa
bababba
ab
abbaabba
bbb
ababa
aabb
Выходные данныеСкопировать
YES
NO
YES
YES
NO
YES
YES
YES
Примечание
В первом примере можно выбрать подстроку s3s4s5s6
и не выполнять второй шаг, тогда получим строку «ababab».
В третьем примере можно выбрать подстроку s1s2s3s4s5
и выполнить второй шаг, тогда получим строку «abababa».
В четвертом примере строка уже чередующаяся.
В шестом примере можно выбрать подстроку s2
и выполнить второй шаг, тогда получим строку «bab»
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e15 + 7;
const int C = 380;
const int B = 64;
void solve() {
string s;
cin >> s;
int cnt2 = 0, cnt3 = 0, cnt = 0, p = 0;
for (int i = 0; i < s.size() - 1; i++) {
if (s[i] == s[i + 1]) {
p++;
} else {
if (p == 1) cnt2++;
if (p == 2) cnt3++;
if (p > 2) cnt++;
p = 0;
}
}
if (p == 1) cnt2++;
if (p == 2) cnt3++;
if (p > 2) cnt++;
//cout << cnt2 << cnt3 << cnt;
if (cnt2 + cnt3 + cnt == 1 && cnt2 == 1) {
cout << "YES\n";
return;
}
if (cnt2 + cnt3 + cnt == 2 && cnt2 == 2) {
cout << "YES\n";
return;
}
if (cnt2 + cnt3 + cnt == 1 && cnt3 == 1) {
cout << "YES\n";
return;
}
if (cnt2 + cnt3 + cnt == 0) {
cout << "YES\n";
return;
}
cout << "NO\n";
}
int32_t main() {
ios_base::sync_with_stdio(0);
cin.tie(0);
srand(time(0));
int tests = 1;
cin >> tests;
while (tests--) {
solve();
}
return 0;
}
что не так
pythonfrom itertools import product def reachable(s): n=len(s) alts=[''.join('a' if (i+j)%2==0 else 'b' for i in range(n)) for j in [0,1]] if s in alts: return True for l in range(n): for r in range(l,n): sub=s[l:r+1] for flip in [0,1]: t=''.join(('b' if c=='a' else 'a') if flip else c for c in sub)[::-1] u=s[:l]+t+s[r+1:] if u in alts: return True return False def code(s): cnt2 = cnt3 = cnt = p = 0 for i in range(len(s)-1): if s[i]==s[i+1]: p+=1 else: if p==1: cnt2+=1 if p==2: cnt3+=1 if p>2: cnt+=1 p=0 if p==1: cnt2+=1 if p==2: cnt3+=1 if p>2: cnt+=1 if cnt2+cnt3+cnt == 1 and cnt2 == 1: return True if cnt2+cnt3+cnt == 2 and cnt2 == 2: return True if cnt2+cnt3+cnt == 1 and cnt3 == 1: return True if cnt2+cnt3+cnt == 0: return True return False bad=[] for n in range(2,11): for tup in product('ab', repeat=n): s=''.join(tup) r=reachable(s) c=code(s) if r!=c: bad.append((s,r,c)) break if bad: break len(bad), bad[:20] (0, [])
По логике у тебя тут ошибки нет — решение корректное.
Я даже проверил его полным перебором всех строк маленькой длины: контрпримеров нет.
Твой код по сути проверяет условие:
можно тогда и только тогда, когда число позиций
i, для которыхs[i] == s[i+1], не больше 2.
То есть твой разбор через cnt2 / cnt3 / cnt — это просто более сложная форма той же самой идеи.
Обозначим “плохую” позицию i, если
cpps[i] == s[i+1]
У чередующейся строки таких позиций должно быть 0.
Теперь посмотрим на операцию:
reverse,Для любых двух соседних символов внутри выбранной подстроки факт
не меняется:
a↔b равенство/неравенство тоже сохраняется.Значит, измениться могут только две границы подстроки:
l-1 и lr и r+1То есть количество плохих позиций можно уменьшить максимум на 2.
Следовательно:
3 или больше, получить 0 уже невозможно;0, 1 или 2 — это всегда можно исправить одной операцией.Ты считаешь блоки одинаковых соседей:
cnt2 — блок длины 1 плохая пара (aa или bb)cnt3 — блок длины 2 (aaa или bbb)cnt — длиннееИ разрешаешь только случаи:
Это и есть ровно случаи, когда общее число плохих пар <= 2.
“Что не так?” — по сути ничего.
Код верный, просто его можно сильно упростить.
cpp#include <bits/stdc++.h> using namespace std; void solve() { string s; cin >> s; int bad = 0; for (int i = 0; i + 1 < (int)s.size(); i++) { if (s[i] == s[i + 1]) bad++; } cout << (bad <= 2 ? "YES\n" : "NO\n"); } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int t; cin >> t; while (t--) solve(); return 0; }
Это не ошибки, но лишнее:
#define int long long — не нужноsrand(time(0)); — вообще не используетсяN, C, B — тоже не используютсяЕсли хочешь, я могу ещё написать короткое строгое доказательство для вставки в разбор на Codeforces.