Codeforces Round #767 (Div. 2)
呜,一学期都没打cf,久而久之变得生疏和害怕了,寒假第一场cf就如此...惨烈,不过也是随着补题才有提升嘛。
C. Meximum Array
mex...之前只在博弈论之类的见到过...没自己实现过呜。
这题很重要的一点是对于固定起点的一系列前缀求mex数组的话,这个数组是单调不减的,并且上升速度不会超过1/1
也就是说,我们设当前位置作为末尾的数组的mex值为 j 的话,每次移动位置后,只要将原数组当前位置的值在mark数组中做好标记,然后让 j 一直++直到遇到未标记的位置,这个 j 就是当前位置作为末尾的数组的mex值。
以上是线性时间复杂度求前缀mex的办法,此题还有个关键是要记录mex数组第一次达到最大值的位置,我一开始想的是,每次增长就记录一下位置,最后自然得到结果。但是这个方法实际上复杂度过高了,因为很有可能2*105的数组只要4位mex就达到了最大(test 2),O(n2)中每次后面的计算都是多余的,因为每个都计算了n次。
这时候灵机一动发现,只要我提前用O(n)算出后缀的mex,那么第一次达到最大也就只要比较 j 等于后缀的mex就行了。注意这里的后缀的开头是指上一次循环中记录的第一次最大位置,也是这次的开始位置(即使在补题时还是大意吃了发WA(悲))。
AC代码:
#include <bits/stdc++.h> #define ll long long #define F freopen("in.txt", "r", stdin) using namespace std; int num[200005], mrk[200005], mex2[200005]; int main() { //F; int t; cin >> t; while (t--) { vector<int> ans; int n; cin >> n; int x = 1; for (int i = 1; i <= n; i++) cin >> num[i]; int j2 = 0; for (int i = n; i > 0; i--) { mrk[num[i]] = true; while (mrk[j2]) j2++; mex2[i] = j2; } memset(mrk, 0, sizeof(mrk)); while (x <= n) { //cout << "x:" << x << " "; int j = 0, maxj = 0; for (int i = x; i <= n; i++) { mrk[num[i]] = true; while (mrk[j]) j++; if (j == mex2[x] || i == n) { maxj = j; x = i + 1; break; } } ans.push_back(maxj); memset(mrk, 0, sizeof(mrk)); } int st = ans.size(); cout << st << endl; for (int i = 0; i < st; i++) cout << ans[i] << (i == st - 1 ? "" : " "); cout << endl; memset(mex2, 0, sizeof(mex2)); } return 0; }
D. Peculiar Movie Preferences
这题草草看了就没细想了,没想到这么简单...1700*可能是因为很多人在C花了很多时间...个人感觉在如果放C题也是1400*
这题有几个关键点,首先单个字母必定是回文,遇到直接输出yes结束此轮循环即可
于是问题变成考虑长度为2、3的两种字符串的组合,并且可以证明如果超过2个的字符串组合是回文,那么一定存在2个字符串组成的回文。
下面就是实现问题,这里我用集合来处理,每次在集合中查询以前有没有出现过其回文并否则就更新集合。
不慎又WA了几发...一次是忘了考虑3长度字符串的拼接...比如abc+cba,一次是没注意到要求按顺序拼接,只能ab+dba但是不能dba+ab。
AC代码:
#include <bits/stdc++.h> #define F freopen("in.txt", "r", stdin) using namespace std; string str[100005]; int main() { //F; int t; cin >> t; while (t--) { set<string> s1, s2, s3; int n, p = 1; cin >> n; for (int i = 0; i < n; i++) cin >> str[i]; for (int i = 0; i < n; i++) { if (str[i].size() == 1) { cout << "yes" << endl; p = 0; break; } if (str[i].size() == 2) { if (str[i][0] == str[i][1]) { cout << "yes" << endl; p = 0; break; } else { char sv_c[3] = {str[i][1], str[i][0]}; string sv(sv_c); if (s1.count(sv) || s2.count(sv)) { cout << "yes" << endl; p = 0; break; } else s1.insert(str[i]); } } if (str[i].size() == 3) { if (str[i][0] == str[i][2]) { cout << "yes" << endl; p = 0; break; } else { char sv_c[3] = {str[i][2], str[i][1]}; string sv(sv_c); char sv3_c[4] = {str[i][2], str[i][1], str[i][0]}; string sv3(sv3_c); if (s1.count(sv) || s3.count(sv3)) { cout << "yes" << endl; p = 0; break; } else { char s_c[3] = {str[i][0], str[i][1]}; string st2(s_c); s2.insert(st2); s3.insert(str[i]); } } } } if (p) cout << "no" << endl; } return 0; }

浙公网安备 33010602011771号