ABC398 题解

A题题解

问题陈述

找出满足以下所有条件的长度为 N N N 的字符串:

  • 每个字符都是 -=
  • 它是一个回文字符串。
  • 正好包含一个或两个 =。如果包含两个 =,则它们相邻。

这样的字符串是唯一的。

限制因素
  • 1 ≤ N ≤ 100 1 \leq N \leq 100 1N100
  • N N N 是整数。
输入

输入内容由标准输入法提供,格式如下

N N N

输出

打印答案。

思路

由于每个回文串都有一个或两个=所以这两的=是对称的而又因为要相邻所以=一定在最中间!

那么我们只需要把 N N N 折半输出-在输出一个或两个=最后在把剩下的-输出即可!

A C   C o d e AC\ Code AC Code
#include <cstdio>
using namespace std;

int main()
{
    int n;
    scanf("%d", &n);
    if (n % 2)
    {
        for (int i = 1; i <= n / 2; i++)
            printf("-");
        printf("=");
        for (int i = 1; i <= n / 2; i++)
            printf("-");
        puts("");
    }
    else
    {
        for (int i = 1; i < n / 2; i++)
            printf("-");
        printf("==");
        for (int i = 1; i < n / 2; i++)
            printf("-");
        puts("");
    }
    return 0;
}

B题题解

问题陈述

我们有七张牌。第 i i i ()张牌 ( i = 1 , … , 7 ) (i=1,\ldots,7) (i=1,,7) 上写着一个整数 A i A_i Ai
请判断是否有可能从这七张牌中选择五张,使所选的牌组成一个葫芦。

当且仅当满足以下条件时,一组五张牌被称为葫芦:

  • 对于不同的整数 x x x y y y ,有三张 x x x 和两张 y y y
限制因素
  • A i A_i Ai 是介于 1 1 1 13 13 13 之间的整数,包括首尾两个整数。
输入

输入内容由标准输入法提供,格式如下

A 1    A 2    A 3    A 4    A 5    A 6    A 7 A_1 \ \ A_2 \ \ A_3 \ \ A_4 \ \ A_5 \ \ A_6 \ \ A_7 A1  A2  A3  A4  A5  A6  A7

输出

如果选择五张牌可以组成葫芦,则打印 Yes;否则打印 No

思路

要想求出是否有三带二的情况只需要用一个桶去存每张牌的数字即可!

c i n > > a , t a + + cin >> a,t_a++ cin>>a,ta++

A C   C o d e AC \ Code AC Code
#include <cstdio>
#include <algorithm>
using namespace std;

int main()
{
    int a[15] = {0};
    for (int i = 1; i <= 7; i++)
    {
        int x;
        scanf("%d", &x);
        a[x]++;
    }
    sort(a + 1, a + 14);
    reverse(a + 1, a + 14);
    if (a[1] >= 3 && a[2] >= 2)
        printf("Yes\n");
    else
        printf("No\n");
    return 0;
}

C题题解

问题陈述

N N N 人,他们的标签从 1 1 1 N N N 。人 i i i 有一个整数 A i A_i Ai

在满足 "其他 N − 1 N-1 N1 人中没有一个人的整数与自己相同 "条件的人中,找出整数最大的那个人,并打印这个人的标签。

如果没有人满足条件,则报告这一事实。

限制因素
  • 1 ≤ N ≤ 3 × 1 0 5 1 \leq N \leq 3\times 10^5 1N3×105
  • 1 ≤ A i ≤ 1 0 9 1 \leq A_i \leq 10^9 1Ai109
  • 所有输入值均为整数。
输入

输入内容由标准输入法提供,格式如下

N N N

A 1    A 2    …    A N A_1 \ \ A_2 \ \ \dots \ \ A_N A1  A2    AN

输出

如果没有人满足 "其他 N − 1 N-1 N1 人中没有人的整数与自己相同 "的条件,则打印 -1

否则,在满足条件的人中,打印整数最大的人的标签。

思路

我们只需要用一个map来标记每个数出现的次数,为什么这里不用桶呢?

N ≤ 1 0 9 N \le 10^9 N109 空间太大了所以不行!

A C   C o d e AC \ Code AC Code
#include <cstdio>
#include <unordered_map>
using namespace std;

int main()
{
    int n;
    scanf("%d", &n);
    int a[500005];               // 记录a[i]
    unordered_map<int, int> cnt; // 记录a[i]的出现次数
    for (int i = 0; i < n; i++)
    {
        scanf("%d", &a[i]);
        cnt[a[i]]++;
    }
    int mx = -1, ans = -1;
    for (int i = 0; i < n; i++)
    {
        if (cnt[a[i]] == 1 && a[i] > mx)
        {
            mx = a[i];
            ans = i + 1;
        }
    }
    printf("%d\n", ans);
    return 0;
}

D题

问题陈述

有一个无限大的二维网格,在坐标 ( 0 , 0 ) (0,0) (0,0) 处有一堆篝火。
在时间 t = 0 t=0 t=0 时,只有单元格 ( 0 , 0 ) (0,0) (0,0) 存在烟雾。

给你一个长度为 N N N 的字符串 S S S ,由 “N”、“W”、“S”、"E "组成。在 t = 1 , 2 , … , N t=1,2,\dots,N t=1,2,,N 时刻,会依次发生以下情况:

  • 风吹起,当时存在的所有烟雾按如下方式移动:
    • 如果 S S S t t h t_{th} tth 字符是 “N”, ( r , c ) (r,c) (r,c) 单元格中的烟雾会移动到 ( r − 1 , c ) (r-1,c) (r1,c) 单元格。
    • 如果是 “W”, ( r , c ) (r,c) (r,c) 单元格中的烟雾会移动到 ( r , c − 1 ) (r,c-1) (r,c1) 单元格。
    • 如果是 “S”, ( r , c ) (r,c) (r,c) 单元格中的烟雾会移动到 ( r + 1 , c ) (r+1,c) (r+1,c) 单元格。
    • 如果是 “E”, ( r , c ) (r,c) (r,c) 单元格中的烟雾会移动到 ( r , c + 1 ) (r,c+1) (r,c+1) 单元格。
  • 如果单元格 ( 0 , 0 ) (0,0) (0,0) 中没有烟雾,则会在单元格 ( 0 , 0 ) (0,0) (0,0) 中产生新的烟雾。

高桥站在 ( R , C ) (R,C) (R,C) 单元格。
对于每个整数 1 ≤ t ≤ N 1 \le t \le N 1tN ,判断在时间 t + 0.5 t+0.5 t+0.5 时,单元格 ( R , C ) (R,C) (R,C) 是否有烟雾存在,并按照要求的格式打印答案。

限制因素
  • N N N 是介于 1 1 1 200000 200000 200000 之间的整数,包括首尾两个整数。
  • S S S 是长度为 N N N 的字符串,由 “N”、“W”、“S”、"E "组成。
  • R R R C C C 是介于 − N -N N N N N (含)之间的整数。
  • ( R , C ) ≠ ( 0 , 0 ) (R,C) \neq (0,0) (R,C)=(0,0)
输入

输入内容由标准输入法提供,格式如下

N    R    C N \ \ R \ \ C N  R  C

S S S

输出

打印一个由 01 组成的 N N N / 字符串。
t t t -th 字符( 1 ≤ t ≤ N 1 \le t \le N 1tN )应该是:

  • 如果在时间 t + 0.5 t+0.5 t+0.5 时,单元格 ( R , C ) (R,C) (R,C) 中存在烟雾,则字符串为 1,否则为 0
  • 否则为0

思路

本题我本来是挂了的但是赛后我想出来了!

1:模拟

首先用一个set<pair<int, int>> st来存储每个烟雾的坐标,在n次循环中每次把st中的每个值更行一下

复杂度:

  • 时间复杂度: O ( N 2 ) O(N^2) O(N2) 你猜能不能过
  • 空间复杂度: O ( 2 N ) O(2N) O(2N) 没问题

所以模拟会超时!

2:换种思路

既然模拟不行那就换种思路!

学过物理的朋友们都知道:
运动是相对的 运动是相对的 运动是相对的
所以所有烟雾向北飘一个对于篝火来说就是向北移,但队于所有烟雾来说就是篝火在向南移!

什么你不懂!来看图!
在这里插入图片描述

风一吹变成了这样如果只盯着篝火看就是烟雾向北飘

在这里插入图片描述

但不要往了篝火产生的烟雾
在这里插入图片描述

有了思路让我们来算一下复杂度:

  • 时间复杂度:
    • 对于每次循环: 处理篝火的x, y坐标,即: O ( 1 ) O(1) O(1)
    • 对于整个程序: N N N 次循环, 即: O ( N ) × O ( 1 ) = O ( N ) O(N) \times O(1) = O(N) O(N)×O(1)=O(N)
  • 空间复杂度:
    • 只需存储一个集合, 即: O ( N ) O(N) O(N)

那么我们怎么判断 ( R , C ) (R,C) (R,C) 是否有烟雾呢?

很简单:因为 ( R , C ) (R,C) (R,C) 只是一个相对位置**我们只需要判断st中是否有 ( x 篝 + R , y 篝 + C ) (x_{篝} + R, y_{篝} + C) (x+R,y+C) 即可!

有了思路那么直接上代码!

A C   C o d e AC \ Code AC Code
#include <bits/stdc++.h>
using namespace std;

int main()
{
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    int n, R, C;
    int x = 0, y = 0;
    string s;
    cin >> n >> R >> C >> s;
    string res = "";
    set<pair<int, int>> st;
    for (int i = 0; i < s.size(); i++)
    {
        char op = s[i];
        int dx = 0, dy = 0;
        switch (op)
        {
        case 'N':
            dx = -1;
            break;
        case 'W':
            dy = -1;
            break;
        case 'S':
            dx = 1;
            break;
        case 'E':
            dy = 1;
            break;
        }
        st.insert({x, y});				//在当前位置生成一个烟雾
        x -= dx, y -= dy;    			//相对移动
        int cpx = x + R, cpy = y + C;   //相对位置
        if (st.count({cpx, cpy}))
            res += '1';
        else
            res += '0';
    }
    cout << res << endl;
    return 0;
}

T h a n k s   f o r   r e a d i n g   ! Thanks \ for \ reading \ ! Thanks for reading !

Logo

集算法之大成!助力oier实现梦想!

更多推荐