AtCoder Beginner Contest 203(Sponsored by Panasonic)(补题)

A - Chinchirorin

在这里插入图片描述
在这里插入图片描述

#include <bits/stdc++.h>
using namespace std;
int a, b, c;
int main() {
    scanf("%d%d%d", &a, &b, &c);
    if (a == b)
        printf("%d\n", c);
    else if (a == c)
        printf("%d", b);
    else if (b == c)
        printf("%d\n", a);
    else
        printf("0");
}

B - AtCoder Condominium

在这里插入图片描述在这里插入图片描述

#include <bits/stdc++.h>
using namespace std;
int main() {
    int n, k;
    scanf("%d%d", &n, &k);
    int res = 0;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= k; j++) {
            res += 100 * i + j;
        }
    }
    cout << res << endl;
    return 0;
}

前两题都是签到题,从第三题开始才有意思

C - Friends and Travel costs

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
题意 就是人在数轴上,从i走到(i+1)要消耗1元,起始状态你有k元,你有n个朋友,在一些点,遇到朋友,他们会给你钱,当钱为0元时,就不能再走了,问你最多能走到多远。
思路 : 肯定不能一个一个点的走,数据范围很大,会超时。要开map或者pair,根据点来排序,能走到朋友点,就走过去零钱,走不到就根据现有的钱走到一个点,当没有朋友时,也是看自己的剩余钱,来判断走到哪。数据范围非常大,还要注意long long的问题

#include <bits/stdc++.h>
using namespace std;
#define ll long long
ll n, k;
map<ll, ll> M;
int main() {
    scanf("%lld%lld", &n, &k);
    for (int i = 1; i <= n; i++) {
        ll x, v;
        scanf("%lld%lld", &x, &v);
        M[x] = M[x] + v;
    }
    ll res = 0;
    for (auto i : M) {
        if (k - (i.first - res) >= 0) {
            k -= (i.first - res);
            res = i.first;
            k += i.second;
        } else {
            break;
        }
    }
    if (k > 0) res += k;
    cout << res << endl;
}

D - Pond

在这里插入图片描述在这里插入图片描述
在这里插入图片描述
题意: 给你一个N×N的矩阵,让你挖出K×K的矩阵,让你求出所有K×K矩阵里的中位数(题目给的定义),并求出众多中位数中的最小值。题目说中位数就是第⌊K2/2⌋+1 个数,就是所谓的中位数。
思路:把原矩阵转化为0/1矩阵,大于等于x的都为1,小于的都为0。x的设置就利用二分来一个一个找,然后就看矩阵中的和是否大于等于⌊K2/2⌋+1.
是的话,说明这个x在K×K矩阵比里面的中位数(题目定义的)小于或等于。
否的话,说明这个x比K×K矩阵里面的中位数还大,不符合题意,找的数太大了,比中位数还大。
可以证明,二分出来的答案就是正确答案
x如果比正确答案还小,那么 L 还不等于 R,说明正确答案还在[L,R]之间 ,那就继续二分[L,R]区间就行,一定能二分出在[L,R]里的正确答案。
x如果比正确答案还大,那么肯定会出现,哪个K×K矩阵里面的0/1求和小于⌊K2/2⌋+1(x比正确答案还大,含有正确答案的那个矩阵,x比那个正确答案大,导致对应位置是0,从而求和小于⌊K2/2⌋+1.),导致进入false,从而减小x

#include <bits/stdc++.h>
using namespace std;
int n, k;
const int N = 888;
int a[N][N];   //原矩阵
int s[N][N];  //0/1前缀和矩阵

bool check(int x) {
    //转化为0/1矩阵,根据与x的大小关系
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            s[i][j] = s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1] + (a[i][j] >= x);
        }
    }
    //求出不同K*K矩阵下的前缀和,两层for循环,就是矩阵的偏移量,i控制上下,j控制左右
    for (int i = k; i <= n; i++) {
        for (int j = k; j <= n; j++) {
            if (s[i][j] - s[i - k][j] - s[i][j - k] + s[i - k][j - k] < (k * k / 2) + 1)
                return false;
        }
    }
    return true;
}

int main() {
    scanf("%d%d", &n, &k);
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            scanf("%d", &a[i][j]);
        }
    }
    int l = 0, r = 1e9;
    while (l < r) {
        int mid = (l + r + 1) >> 1;
        if (check(mid))
            l = mid;
        else
            r = mid - 1;
    }
    printf("%d\n", l);
    return 0;
}

To be continued
如果你有任何建议或者批评和补充,请留言指出,不胜感激

  • 7
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值