Loading

AtCoder Beginner Contest 339




B - Langton's Takahashi

难度: ⭐⭐

题目大意

给定一个n * m的网格, 并且每一行和每一列都是首尾相连的, 每行的最后一个格子再往右就是这行的第一个格子, 第一个格子向左就是最后一个格子; 列也同理; 默认每个格子初始为白色; 小莫位于(1, 1), 方向朝上;
当小莫位于某个格子时, 如果当前单元格是白色,则将其重新涂成黑色,前进方向顺时针旋转90度,然后沿着他面对的方向向前移动一个单元格。如果是黑色,则将当前单元格重新涂成白色,逆时针旋转90度,然后沿着他所面对的方向向前移动一个单元格。
将上述步骤进行k次, 打印最后格子的颜色分布, '.'表示白色, '#'为黑色;

解题思路

模拟就行, 没啥好说的;

神秘代码

#include<bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define endl '\n'
using namespace std;
const int N = 2e5 + 10, mod = 998244353, inf = 1e18;
typedef pair<int, int> PII;
int n, m, res;
int g[110][110];
int dx[4] = {0, 1, 0, -1}, dy[4] = {1, 0, -1, 0};
signed main(){
    int k;
    cin >> n >> m >> k;
    int a = 1, b = 1, d = -1;
    while(k--){
        if(g[a][b]){
            g[a][b] = 0;
            d = (d - 1 + 4) % 4;
            a += dx[d], b += dy[d];
        }
        else{
            g[a][b] = 1;
            d = (d + 1) % 4;
            a += dx[d], b += dy[d];
        }
        if(a > n) a = 1;
        else if(a < 1) a = n;
        if(b > m) b = 1;
        else if(b < 1) b = m;
    }
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= m; j++){
            if(g[i][j]) cout << '#';
            else cout << '.';
        }
        cout << endl;
    }
    return 0;   
}




C - Perfect Bus

难度: ⭐⭐

题目大意

给定一个公交车n个站牌的上下车情况, 这期间车上的人数始终不能小于0, 请问满足条件的最小的初始人数是多少;

解题思路

很简单, 只需要当人数小于0的时候把人数补到0即可;

神秘代码

#include<bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define endl '\n'
using namespace std;
const int N = 2e5 + 10, mod = 998244353, inf = 1e18;
typedef pair<int, int> PII;
int n, m, res;
signed main(){
    cin >> n;
    for(int i = 1; i <= n; i++){
        int a;
        cin >> a;
        res += a;
        if(res < 0){
            res = 0;
        }
    }
    cout << res;
    return 0;   
}




D - Synchronized Players

难度: ⭐⭐⭐

题目大意

在一个n * n的网格中有两名玩家, 每次我们可以选择上下左右中的一个方向, 两人都朝这个方向前进一格; 如果某人面前是障碍物或者边界则这名玩家不移动; 请问最少进行多少次可以让两名玩家同时位于同一个格子; 无解则输出-1;

解题思路

由于没有什么规律, 所以bfs打暴力即可; 因为数据很小, 所以可以开一个四维数组来去重, 以便判断是否有解;

神秘代码

#include<bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define endl '\n'
using namespace std;
const int N = 2e5 + 10, mod = 998244353, inf = 1e18;
typedef pair<int, int> PII;
int n, m, res;
int xa, ya, xb, yb;
char g[100][100];
bool st[62][62][62][62];
int dx[] = {1, 0, -1, 0}, dy[] = {0, 1, 0, -1};
struct node{
    int xa, ya, xb, yb;
    int num;
};
bool check(int x, int y){
    if(x >= 1 && x <= n && y >= 1 && y <= n && g[x][y] != '#'){
        return true;
    }
    else return false;
}
int bfs(){
    queue<node> q;
    q.push({xa, ya, xb, yb, 0});
    while(q.size()){
        auto t = q.front();
        q.pop();
        if(t.xa == t.xb && t.ya == t.yb){
            return t.num;
        }
        for(int i = 0; i < 4; i++){
            int x1 = t.xa + dx[i], y1 =t.ya + dy[i];
            int x2 = t.xb + dx[i], y2 =t.yb + dy[i];
            if(!check(x1, y1)){
                x1 = t.xa, y1 = t.ya;
            }
            if(!check(x2, y2)){
                x2 = t.xb, y2 = t.yb;
            }
            if(!st[x1][y1][x2][y2]) {
                q.push({x1, y1, x2, y2, t.num + 1});
                st[x1][y1][x2][y2] = true;
            }
        }
    }
    return -1;
}
signed main(){
    cin >> n;
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            cin >> g[i][j];
            if(g[i][j] == 'P'){
                if(xa) xb = i, yb = j;
                else xa = i, ya = j;
            }
        }
    }
    cout << bfs();
    return 0;   
}




E - Smooth Subsequence

难度: ⭐⭐⭐

题目大意

给定一个长度为n的数组A, 求其满足条件的子序列的最大长度是多少;
要求该子序列相邻的数之间差距不能超过m;

解题思路

我一开始想的是用dp, 并且根据题意对于每个数肯定是能接就接; 如果当前进行到了Ai, Ai要接在以(Ai - m, Ai + m)其中一个数结尾的子序列后面, 假设把所有满足条件的子序列后面都接上Ai, 我们发现其实只需要保留其中最长的一个子序列就行, 因为他们都是以Ai, 是等效的; 所以我们可以用线段树来维护以x结尾的子序列的最大长度; 对于Ai就只需要从(Ai - m, Ai + m)中找出最大值即可; 所以其实也用不到dp;

神秘代码

#include<bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define endl '\n'
using namespace std;
const int N = 5e5 + 10, mod = 998244353, inf = 1e18;
typedef pair<int, int> PII;
int n, m, res;
int p[N];
struct node{
    int l, r;
    int maxn;
}tr[4 * N];
void pushup(int u){
    tr[u].maxn = max(tr[u << 1].maxn, tr[u << 1 | 1].maxn);
}
void build(int u, int l, int r){
    tr[u] = {l, r, 0};
    if(l == r) return;
    int mid = l + r >> 1;
    build(u << 1, l, mid);
    build(u << 1 | 1, mid + 1, r);
}
void modify(int u, int x, int num){
    if(tr[u].l == tr[u]. r && tr[u].l == x){
        if(num > tr[u].maxn){
            tr[u].maxn = num;
        }
    }
    else{
        int mid = tr[u].l + tr[u].r >> 1;
        if(x <= mid) modify(u << 1, x, num);
        else modify(u << 1 | 1, x, num);
        pushup(u);
    }
}
int query(int u, int l, int r){
    if(tr[u].l >= l && tr[u].r <= r){
        return tr[u].maxn;
    }
    else{
        int mid = tr[u].l + tr[u].r >> 1;
        int res = 0;
        if(l <= mid) res = max(res, query(u << 1, l, r));
        if(r > mid) res = max(res, query(u << 1 | 1, l, r));
        return res;
    }
}
signed main(){
    cin >> n >> m;
    int k = 0;
    for(int i = 1; i <= n; i++){
        cin >> p[i];
        k = max(k ,p[i]);
    }
    build(1, 1, k);
    for(int i = 1; i <= n; i++){
        int maxn = query(1, max(0ll, p[i] - m), min(k, p[i] + m));
        modify(1, p[i], maxn + 1);
    }
    cout << query(1, 1, k);
    return 0;   
}




F - Product Equality

难度: ⭐⭐⭐

题目大意

给定一个长度为n的数组A, 找出满足条件的三元组(i, j, k)的数量: 1 <= i, j, k <= n, 并且 Ai * Aj = Ak;

解题思路

要求很简单, 但是本题的难点在于Ai的范围是101000; 可以用python的大数来做, 如果用c++的话就只能靠哈希来赌了; 为了提高概率这里我们用双哈希; 也就是对于每个Ai, 我们用两个数对其取模, 用这两个数的二元组来代表这个数; 当然不放心的话也可以再多几层哈希;

神秘代码

#include<bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define endl '\n'
using namespace std;
const int N = 5e5 + 10, mod = 998244353, inf = 1000000993;
typedef pair<int, int> PII;
int n, m, res;
int p[2][N];
map<PII, int> mp;
signed main(){
    cin >> n;
    for(int i = 1; i <= n; i++){
        string s;
        cin >> s;
        for(int j = 0; j < s.size(); j++){
            p[0][i] = (p[0][i] * 10 + (s[j] - '0')) % mod;
            p[1][i] = (p[1][i] * 10 + (s[j] - '0')) % inf;
        }
        mp[{p[0][i], p[1][i]}]++;
    }
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            res += mp[{p[0][i] * p[0][j] % mod, p[1][i] * p[1][j] % inf}];
        }
    }
    cout << res;
    return 0;   
}
posted @ 2024-02-20 17:26  mostimali  阅读(17)  评论(0编辑  收藏  举报