AtCoder Beginner Contest 210

AtCoder Beginner Contest 210

A - Cabbages

题意:

题解:

代码:

#include <bits/stdc++.h>

#define int long long
#define debug(x) cout << #x << " = " << x << endl;
using namespace std;

int const MAXN = 2e5 + 10;
int n, m, T, a, x, y;

signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cin >> n >> a >> x >> y;
    cout << min(a, n) * x + max ((int)0, (n - a) )* y;
    return 0;
}

B - Bouzu Mekuri

题意:

题解:

代码:

#include <bits/stdc++.h>

#define int long long
#define debug(x) cout << #x << " = " << x << endl;
using namespace std;

int const MAXN = 2e5 + 10;
int n, m, T, a[MAXN];

signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cin >> n;
    string s;
    cin >> s;
    int cnt = 0;
    for (int i = 0; i < s.size(); ++i) {
        if (s[i] == '1') {
            if (!(i & 1)) puts("Takahashi");
            else puts("Aoki");
            return 0;
        }
    }
    return 0;
}

C - Colorful Candies

题意:

题解:

代码:

#include <bits/stdc++.h>

#define int long long
#define debug(x) cout << #x << " = " << x << endl;
using namespace std;

int const MAXN = 3e5 + 10;
int n, m, T, a[MAXN];
unordered_map<int, int> mp;

signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cin >> n >> m;
    for (int i = 1; i <= n; ++i) cin >> a[i];
    int cnt = 0, res = 0;
    for (int i = 1; i <= m; ++i) {
        if (mp[a[i]] == 0) cnt++;
        mp[a[i]] ++;
        res = max(res, cnt);
    }
    for (int i = m + 1; i <= n; ++i) {
        // debug(cnt);
        if (mp[a[i]] == 0) cnt++;
        mp[a[i]]++;
        if (mp[a[i - m]] == 1) cnt--;
        mp[a[i - m]]--;
        res = max(res, cnt);
    }
    cout << res;
    return 0;
}

D - National Railway

题意: 给出一张H * W的网格,网格上每个点有个权值 a [ i ] [ j ] a[i][j] a[i][j],给出权值C。现在让你找到两个点(x1, y1),(x2, y2),使得 a [ x 1 ] [ y 1 ] + a [ x 2 ] [ y 2 ] + C ( ∣ x 1 − x 2 ∣ + ∣ y 1 − y 2 ∣ ) a[x1][y1] + a[x2][y2] + C(|x1-x2| + |y1-y2|) a[x1][y1]+a[x2][y2]+C(x1x2+y1y2) 最小。 2 < = H , W < = 1 e 3 , 1 < = C < = 1 e 9 , 1 < = a i , j < = 1 e 9 2<=H, W<=1e3, 1<=C<=1e9,1<=a_{i,j}<=1e9 2<=H,W<=1e3,1<=C<=1e9,1<=ai,j<=1e9

题解:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qY5nksPA-1628592363303)(https://i.loli.net/2021/08/06/E8VgpftFrTmeluA.jpg)]

上面分析的是x1 < x2, y1 < y2的情况,对于其他方向,只需要把a数组的行给reverse一下即可,具体可以好好思考下原因。

代码:

#include <bits/stdc++.h>

#define int long long
#define debug(x) cout << #x << " = " << x << endl;
using namespace std;

int const MAXN = 1e3 + 10;
int H, W, T, a[MAXN][MAXN], d[MAXN][MAXN], C;

signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cin >> H >> W >> C;
    for (int i = 1; i <= H; ++i) 
        for (int j = 1; j <= W; ++j) 
            cin >> a[i][j];

    int res = 1e18;
    for (int t = 1; t <= 2; ++t) {
        memset(d, 0x3f, sizeof d);
        for (int i = 1; i <= H; ++i) 
            for (int j = 1; j <= W; ++j) {
                if (i > 1) d[i][j] = min(d[i][j], d[i - 1][j]);
                if (j > 1) d[i][j] = min(d[i][j], d[i][j - 1]);
                res = min(res, a[i][j] + C * (i + j) + d[i][j]);
                d[i][j] = min(d[i][j], a[i][j] - C * (i + j));
            }
        reverse(a + 1, a + 1 + H);
    }
    cout << res;
    return 0;
}

E - Ring MST

题意: 给定一张n个点的图,编号从0 ~ n - 1。给定m个关系,每个关系给定a和c,表示能把任意一个点x(0<=x<=n-1)与(x + a) % n连一条边,即 x----(x + a) % n,代价为c。问能否使用这个关系任意次,使得整张图变为一个连通块。 1 < = N < = 1 e 9 , 1 < = M < = 1 e 5 , 1 < = C < = 1 e 9 1<=N<=1e9, 1<=M<=1e5,1<=C<=1e9 1<=N<=1e9,1<=M<=1e5,1<=C<=1e9

题解: 规律+贪心。我们发现每次使用规则任意次可以把n个点转换为gcd(n, a)个连通块。因此贪心来看,我们应该从最小代价的规则开始使用,然后最后判断连通块数目是否为1。为什么这么做是对的呢?因为存在gcd(n, x) < n / 2 (0<=x<=n-1),即连通块数目都会比原来的一半还少 ,这样我如果从花费最少的开始用,就能够保证总费用最少。

代码:

#include <bits/stdc++.h>

#define int long long
#define debug(x) cout << #x << " = " << x << endl;
using namespace std;

int const MAXN = 2e5 + 10;
int n, m, T;
typedef pair<int, int> PII;
PII a[MAXN];

signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cin >> n >> m;
    for (int i = 1; i <= m; ++i) {
        cin >> a[i].second >> a[i].first ;
    }
    sort(a + 1, a + 1 + m);
    int res = 0, all = n;
    for (int i = 1; i <= m; ++i) {
        int now = __gcd(a[i].second, all);
        res += a[i].first * (all - now);
        all = now;
        if (all == 1) break;
    }
    if (all == 1) cout << res;
    else cout << -1;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值