Codeforces Round 1073 (Div. 2)
A
void solve() {
int n;
cin >> n;
vector<pair<int, int>> a(n);
for (int i = 0; i < n; i++) {
cin >> a[i].first;
if (i & 1) a[i].second = 0;
else a[i].second = 1;
}
sort(a.begin(), a.end());
for (int i = 1; i < n; i++) {
if (a[i].second == a[i - 1].second) {
cout << "NO" << '\n';
return;
}
}
cout << "YES" << '\n';
}
B
void solve() {
int n;
cin >> n;
vector<int> a(n);
int cnt0 = 0, cnt1 = 0;
for (auto &i : a) {
cin >> i;
if (i == 0) cnt0++;
if (i == 1) cnt1++;
}
// 小插曲:这个cnt0 = 0想到了,但是没加上 WA了一发
if ((cnt0 > 1 && cnt1 == 0) || cnt0 == 0) {
cout << "NO" << '\n';
return;
}
cout << "YES" << '\n';
}
C
C真难啊,我想了好半天想不到问题的本质,没想到好方法
欸我去,这么简单的吗?我以为玩家选择的序列只能是连续的,题目理解问题
那我就只需要把左半边的1和右半边数量相等的0调换位置即可
也就是说Alice只要能操作,Alice必赢,否则Bob赢
void solve() {
int n;
cin >> n;
string a;
cin >> a;
int cnt0 = count(a.begin(), a.end(), '0');
vector<int> idx;
for (int i = 0; i < n; i++) {
if (i < cnt0 && a[i] == '1') idx.push_back(i);
else if (i >= cnt0 && a[i] == '0') idx.push_back(i);
}
if (idx.empty()) {
cout << "Bob" << '\n';
}
else {
cout << "Alice" << '\n';
int k = idx.size();
cout << k << '\n';
for (int i = 0; i < k; i++) {
cout << idx[i] + 1 << " \n"[i == k - 1 ? 1 : 0];
}
}
}
D
又是一道题目很绕但是很简单的题
我们要构造一个s的子序列t,要求t要优于s,即满足以下条件:
- s是t的前缀,且s != t
- 在s与t的第一个不相等的位置idx,要求
t[idx] = '(',s[idx] = ')'
因为t是s的子序列,也就是说第一个条件是无法满足的,我们只需要看第二个条件
我们希望t尽可能的长,所以希望尽可能少的删除s中的字符来构造t
既然有一个位置不相等,说明该位置的字符被删除了,而且被删除的字符后面还是'('
这样才能满足第二个条件
但是如果只删除这一个字符,t就不平衡了,所以我们还有删除idx后面的一个'('
这样就平衡了,也符合条件
总的来说,就是希望找到一个')',它后面跟着一个'(',并且后面至少还有一个'('用于删除
我之前一直执着于被删除的字符是s中第一个遇到的'('字符,但是发现面对((()))()()没法构造,也就是这个字符串中的索引3,发现删了这个字符索引3这个位置依然是')'不满足条件
最后发现才发现得是第一个后面紧跟着'('的')'才行
((())())这样就行了
然后一直这样想,就连看到题解也很困惑,最后才豁然开朗
只能说,每一步思考都要验证这一步的正确性啊
那么为什么代码这样写是对的,因为你可以将第一次遇到的和后面跟着的连续的'('看作一个
第一个遇到的')'后面的cnt和这一连串后面的cnt数量是一样的
void solve() {
int n;
cin >> n;
string s;
cin >> s;
int idx = s.find(')');
int cnt = 0;
for (int i = idx + 1; i < n; i++) {
if (s[i] == '(') cnt++;
}
if (cnt >= 2) {
cout << n - 2 << '\n';
}
else {
cout << -1 << '\n';
}
}
浙公网安备 33010602011771号