Codeforces Global Round 12
Avoid Trygub
题意:
给你一个字符串,重排它让它不出现$"trygub"$子序列。$n \leq 100$。
题解:
对这个字符串的字符直接排序即可。
Balls of Steel
题意:
给你$n$个点和$k$,每次选择一个点,使得和它的曼哈顿距离小于$k$的点都被它吸引(到它的位置),问多少次操作能使所有点都在一个位置,不能则输出$-1$。$n \leq 100$。
题解:
显然要么一次,要么不能。暴力判断一下点之间的距离就行。
Errich-Tac-Toe (Easy Version)
题意:
一个$n * n$的棋盘上有$'.'$和$'X'$,三个$'X'$横着或竖着连续,则算赢局,否则算平局,给出一个局面,现在你需要把最多$\lfloor \frac{k}{3} \rfloor$的位置($k$为$'X'$的个数)改成$'O'$,让它变成平局,输出方案。
题解:
想了很多方法$QAQ$,但是完全没注意到染色的笨蛋。考虑染色,其实我们可以发现,连着的三个$'X'$坐标($x_i,y_i$)的和$x_i+y_i$构成模$3$的完全剩余系,按照这个染色。这样子我们只需要算出每种颜色的$'X'$有多少,把最少$'X'$的颜色的$'X'$全部染成$'O'$即可。
Errich-Tac-Toe (Hard Version)
题意:
一个$n * n$的棋盘上有$'.'$和$'X'$和$‘O’$,三个$'X'$或者三个$'O'$横着或竖着连续,则算赢局,否则算平局,给出一个局面,现在你需要把最多$\lfloor \frac{k}{3} \rfloor$的位置($k$为$'X'$的个数)改成$'O'$,反之亦然,让它变成平局,输出方案。
题解:
同上,我们保证一种颜色没有$'X'$,另一种颜色没有$'O'$即可。
总结:
碰到这种连着的题,可以考虑模$k$染色的做法。
Rating Compression
题意:
给出一个序列,问对于$1 \leq i \leq n$,长度为$i$构成的滑动窗口的最小值形成的长度$n-i+1$的序列是不是一个排列。输出一个长度是$n$的字符串,第$i$位$[0/1]$表示长度为$i$的情况。
题解:
考虑一个数向左向右延伸多长,这个区间内还是以它为最小值,若窗口长度小于这个区间,显然生成的序列就不是排列。考虑滑动窗口长度是$i$排列的性质:$1$到$n-i+1$都需要出现在排列中,排列长度是$1$到$n-i+1$。则如果$n-i+1$不出现在原序列,这个排列必不存在。因为考虑到$1$一定是最小的,则延伸长度是$n$的区间一定会是$1$,记录$1$,考虑$2$,如果延伸长度不是$n-1$,则说明$1$不在端点,则长度是$n-1$的滑动窗口必然非法。否则记录$2$。同样的考虑$3$,并假设长度$n-1$的滑动窗口合法,显然$1$和$2$要么分别在两端点,要么连着,且$1$咋在端点,则$2$的延伸长度是$n-1$。记录$3$。即$i$合法时,必须有$1$到$i$的记录,此时滑动窗口的长度是$n-i+1$。考虑重复的情况:$1 \ 3 \ 2 \ 1$,算出滑动窗口长度是$2$时的序列:$1 \ 2 \ 1$。按照上面的过程,滑窗长度是$3$时,没有记录$2$,但是记录了两个1,然后在滑窗长度是$2$是,记录了$2$,此时也是满足3个的。但是显然这个生成序列不满足。此时$set$去重即可。
AC代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int N = 3e5 + 5; 4 int l[N], r[N]; 5 int s[N], a[N], cnt[N]; 6 bool vis[N]; 7 char str[N]; 8 vector<int>v[N]; 9 set<int>ss; 10 void solve() 11 { 12 int n; 13 scanf("%d", &n); 14 for (int i = 1; i <= n; ++i) 15 { 16 vis[i] = 0; 17 str[i] = '0'; 18 v[i].clear(); 19 cnt[i] = 0; 20 } 21 ss.clear(); 22 for (int i = 1; i <= n; ++i) 23 scanf("%d", &a[i]), vis[a[i]] = 1; 24 int top = 0; 25 for (int i = 1; i <= n; ++i) 26 { 27 while (top && a[i] < a[s[top - 1]]) 28 r[s[--top]] = i - 1; 29 s[top++] = i; 30 } 31 while (top) 32 r[s[--top]] = n; 33 for (int i = n; i; --i) 34 { 35 while (top && a[i] < a[s[top - 1]]) 36 l[s[--top]] = i + 1; 37 s[top++] = i; 38 } 39 while (top) 40 l[s[--top]] = 1; 41 for (int i = 1; i <= n; ++i) 42 v[r[i] - l[i] + 1].push_back(a[i]); 43 for (int i = n; i; --i) 44 { 45 if (!vis[n - i + 1]) 46 break; 47 for (auto num : v[i]) 48 ss.insert(num); 49 if (ss.size() == n - i + 1) 50 str[i] = '1'; 51 } 52 for (int i = 1; i <= n + 1; ++i) 53 printf("%c", i <= n ? str[i] : '\n'); 54 } 55 int main() 56 { 57 int t; 58 scanf("%d", &t); 59 while (t--) 60 solve(); 61 return 0; 62 }