Loading

AtCoder Beginner Contest 342




B - Which is ahead?

难度: ⭐

题目大意

给定n个人的位置顺序, 现有m次询问, 给出a, b两个人, 问谁在前面;

解题思路

模拟就行;

神秘代码

#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, k;
int p[N];
signed main(){
    cin >> n;
    for(int i = 1; i <= n; i++){
        int x;
        cin >> x;
        p[x] = i;
    }
    cin >> m;
    for(int i = 1; i <= m; i++){
        int a, b;
        cin >> a >> b;
        if(p[a] < p[b]) cout << a << endl;
        else cout << b << endl;
    }
	return 0;
}




C - Many Replacement

难度: ⭐⭐⭐

题目大意

现有字符串s, 现有m次操作, 每次操作给出两个字符a, b; 要求把字符串s中所有的a都换成b; 最后输出字符s

解题思路

本题可以用哈希来做, 开一个长度为26的数组p[26]用来表示此时的字母x表示的是哪个字母, 初始当然都是自己; 每次修改时, 先遍历26个字母, 看都有谁的p[i] = a, 然后把它们都改成b即可; 最后输出s的时候输出每个字母所对应的p即可;

神秘代码

#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, k;
string s;
int p[N];
signed main(){
    cin >> n >> s >> m;
    for(int i = 0; i < 26; i++) p[i] = i;
    while(m--){
        char a, b;
        cin >> a >> b;
        for(int i = 0; i < 26; i++){
            if(p[i] == a - 'a') p[i] = b - 'a';
        }
    }
    for(int i = 0; i < n; i++){
            printf("%c", p[s[i] - 'a'] + 'a');
        }
	return 0;
}




D - Square Pair

难度: ⭐⭐⭐

题目大意

给定n个数字Ai, 问有多少个满足条件的二元组(i, j), 条件如下
一是Ai * Aj是一个平方数;
二是i < j;

解题思路

暴力做法是O(n2)显然会超时, 所以要从平方数下手; 已知定理, 任何一个数都可以化为多个质数的乘积; 如果a * b是一个平方数并且a != b的话, 我们把组成a和b的质数都列出来, 并且让两者同一质数的数量相加, 那么我们会发现所有质数的数量都是偶数, 因为这样才会相乘是一个平方数; 由这一发现还不足以解题, 所以我们可以先把a和b进行化简, 拿a来说, 把组成a的质数列出来之后可以把其中数量大于等于2的质数数量减到0或1, 用代码实现就是遍历小于a的平方数, 让a减去其中可以被a整除的; 化简完后我们发现a = b, 这样我们就可以解题了; 把所有数化简后遍历数组, 对于数字a, 结果res就加上cnt(a) - 1; cnt(a)指数组中a的数量; 又因为二元组要求i < j; 所以最后res要除以二;
本题还有个特殊情况就是0, 0可以和任何数搭配, 所以只需要关心i < j即可; 对于下标i, 我们用cnt[i]记录前i个数字中有几个0; 对于每个0, 我们将其看作二元组的前一个; 所以结果加上n - cnt[i]即可;

神秘代码

#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;
string s;
int p[N], cnt[N];
map<int, int> mp;
signed main(){
    cin >> n;
    for(int i = 1; i <= n; i++){
        cin >> p[i];
        for(int j = 2; j * j <= p[i]; j++){
            while(p[i] % (j * j) == 0){
                p[i] /= (j * j);
            }
        }
        mp[p[i]]++;
        cnt[i] = cnt[i - 1] + (p[i] == 0);
    }
    int a = 0, b = 0, c = n - 1;
    for(int i = 1; i <= n; i++){
        if(p[i] == 0) {
            a += n - cnt[i];
        }
        else b += (mp[p[i]] - 1);
    }
    cout << a + b / 2;
	return 0;
}




E - Last Train

难度: ⭐⭐⭐⭐

题目大意

现有n个车站, 每个车站都有6个属性, l, d, k, c, A, B; 从时刻l开始发车, 每隔时间d发一辆, 一共发k辆; 并且火车是从A点前往B点, 所需时间是c; 设F(x)指从车站x的车最晚什么时候出发可以到车站n;

解题思路

因为所有车站的目标都是n, 那么我们可以从车站n开始反向进行最短路dijkstra; 找到从v出发可以到达u的最晚的一班车; 如果v的l + c > F(u); 则说明从v来的车赶不上u的满足条件的最晚的那班车; 否则我们找的车次就是num = min((F(u) - (l + c)) / d, k - 1); 然后就可以用l + num * d来更新F(u);

神秘代码

#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 = 2e18;
typedef pair<int, int> PII;
int n, m, res;
string s;
struct node{
    int u, l, d, k, c;
};
node P[N];
vector<node> v[N];
int dis[N];
void dijkstra(){
    for(int i = 1; i <= n; i++) dis[i] = -inf;
    priority_queue<PII> heap;
    heap.push({inf, n});
    dis[n] = inf;
    while(heap.size()){
        PII t = heap.top();
        heap.pop();
        int id = t.second;
        for(auto x : v[id]){
            int y = dis[id] - (x.l + x.c); 
            if(y < 0) continue;
            int num = x.l + min(y / x.d, x.k - 1) * x.d;
            if(num > dis[x.u]){
                dis[x.u] = num;
                heap.push({dis[x.u], x.u});
            }
        }
    }
}
signed main(){
    cin >> n >> m;
    for(int i = 1; i <= m; i++){
        int l, d, k, c, a, b;
        cin >> l >> d >> k >> c >> a >> b;
        v[b].push_back({a, l, d, k, c});
    }
    dijkstra();
    for(int i = 1; i < n; i++){
        if(dis[i] == -inf) cout << "Unreachable" << endl;
        else cout << dis[i] << endl;
    }
	return 0;
}




F - Black Jack

难度: ⭐⭐⭐⭐

posted @ 2024-03-02 17:47  mostimali  阅读(12)  评论(0编辑  收藏  举报