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 }
View Code

 

posted @ 2020-12-09 13:05  Aya_Uchida  阅读(232)  评论(0编辑  收藏  举报