【解题总结】SEERC 2019(Codeforces Gym 102392)

我解决的:D、I、E。

没看的:H、K。

旁观的:B、G。

看了但没做出来的:A、C、F、J。

E Life Transfer

简单题,略。

D Cycle String?

题意:给定一个长为 2 N 2N 2N 的串,问能否将其重新排列使得新串的每一个长度为 N N N 的循环子串(即这个子串可以由原串的某个后缀和前缀拼接而成)互不相同,如果能要给出一个构造。

统计每一个字符出现的数目,然后分类讨论。

  1. 只有一种字符,那必然无解。
  2. 只有两种字符,且某种字符出现了不少于 2 N − 2 2N-2 2N2 次,那么就可能无解,要看 N N N 是否为 1 1 1 或者 2 2 2,或者大于 2 2 2。这里讨论一下即可。
  3. 除上面两种情况外都是有解的。设出现次数最多的字符为 a a a,如果 a a a 出现了不超过 N N N 次,那么只要对原字符串排序即可;否则在排序完原字符串后,要用一个除 a a a 之外的字符把那一段 a a a 分割为左右两部分,使得左半部分长度恰为 N N N。可以证明这一构造是合法的。

K Stranded Robot

大模拟,略。应该不是很难写…

G Projection

题意:有一个 n × m × h n \times m \times h n×m×h 的三维网格,每一个网点上可能有一个方块。给定这个网格沿着两个方向投影得到的画面,大小分别为 n × m n \times m n×m n × h n \times h n×h,问为了达成这样的投影,这个网格中最多要有几个方块、最少要有几个方块,并给出两种情况下方块的坐标列表。多解时输出字典序最小的那个。

n n n 坐标遍历,每一层进行构造。显然,每一层的答案互不影响。

无解当且仅当这一层在 n × m n\times m n×m 的投影中有影子,但在 n × h n\times h n×h 的投影中没有影子,或者反过来。

如果这一层在 n × m n\times m n×m 的投影中有 a a a 个方块的影子,在 n × h n\times h n×h 的投影中有 b b b 个方块的影子,那么这一层最多可以有 a b a b ab 个方块,最少可以有 max ⁡ ( a , b ) \max(a, b) max(a,b) 个方块。

对于后者要求出字典序最小的方案,只需要按照 m m m 坐标或者 h h h 坐标递增方向构造方块即可。

【解题总结】SEERC 2019(Codeforces Gym 102392)_第1张图片

#include 
#define MAXN 105
using namespace std;
int n, m, h, a[MAXN][MAXN], b[MAXN][MAXN];
int cntm[MAXN], cnth[MAXN];
int lstm[MAXN], lsth[MAXN];
char s[MAXN];
int main(){
   
    scanf("%d%d%d", &n, &m, &h);
    for (int i = 1; i <= n; ++i){
   
        scanf("%s", s + 1);
        cntm[i] = 0;
        for (int j = 1; j <= m; ++j)
            a[i][j] = (s[j] == '1' ? 1: 0), cntm[i] += a[i][j];
    }
    for (int i = 1; i <= n; ++i){
   
        scanf("%s", s + 1);
        cnth[i] = 0;
        for (int j = 1; j <= h; ++j)
            b[i][j] = (s[j] == '1' ? 1: 0), cnth[i] += b[i][j];
    }
    
    // -1
    int maxi = 0, mini = 0;
    for (int i = 1; i <= n; ++i){
   
        if ((cntm[i] > 0 && cnth[i] == 0) || (cnth[i] > 0 && cntm[i] == 0)){
   
            printf("-1\n");
            return 0;
        } 
        maxi += cntm[i] * cnth[i];
        mini += max(cntm[i], cnth[i]);
    }
    
    // construct
    printf("%d\n", maxi);
    for (int i = 1; i <= n; ++i){
   
        for (int j = 1; j <= m; ++j)
            for (int k = 1; k <= h; ++k)
                if (a[

你可能感兴趣的:(解题总结)