Atcoder Beginner Contest 305 A~E

A - Water Station

题目
0~100km每隔5km有一个饮水站,包括起点和终点共21个,给定n,问最近的一个饮水站的位置

  • 对5取模得到t,然后判断t是不是小于3,小于3就减去,否则加上5-t
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
#define x first
#define y second
#define INF 0x3f3f3f3f
#define vi vector<int>
#define pii pair<int, int>
#define mset(x, v) memset(x, v, sizeof x)
#define all(x) ((x).begin()), ((x).end())
#define uf(i, j, k) for (int i = j; i <= k; i ++)
#define df(i, j, k) for (int i = j; i >= k; i --)

using namespace std;

void solve()
{
    int n;
    cin >> n;
    int t = n % 5;
    if (t < 3) cout << (n - t) << endl;
    else cout << (n + 5 - t) << endl; 
}

signed main()
{
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    int t = 1;
    while (t --) solve();
    return 0;
}

B - ABCDEFG

题目
ABCDEFG每个点之间有一定的距离,给定两个点,问之间的距离

  • 前缀和
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
#define x first
#define y second
#define INF 0x3f3f3f3f
#define vi vector<int>
#define pii pair<int, int>
#define mset(x, v) memset(x, v, sizeof x)
#define all(x) ((x).begin()), ((x).end())
#define uf(i, j, k) for (int i = j; i <= k; i ++)
#define df(i, j, k) for (int i = j; i >= k; i --)

using namespace std;

void solve()
{
    char p, q;
    cin >> p >> q;
    int a[] {0, 3, 1, 4, 1, 5, 9};
    for (int i = 1; i < 7; i ++) a[i] += a[i - 1];
    if (p < q) swap(p, q);
    cout << a[p - 'A'] - a[q - 'A'] << endl;
}

signed main()
{
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    int t = 1;
    // cin >> t;
    while (t --) solve();
    return 0;
}

C - Snuke the Cookie Picker

题目
给一个二维矩阵,在长宽至少为2的矩形中每个方块上都有一个cookie,现在拿走一块cookie,问这块cookie的位置

  • 题目说答案唯一,那么直接划分出一个矩阵,在这个矩阵里面找即可
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
#define x first
#define y second
#define INF 0x3f3f3f3f
#define vi vector<int>
#define pii pair<int, int>
#define mset(x, v) memset(x, v, sizeof x)
#define all(x) ((x).begin()), ((x).end())
#define uf(i, j, k) for (int i = j; i <= k; i ++)
#define df(i, j, k) for (int i = j; i >= k; i --)

using namespace std;

const int N = 510;
char mp[N][N];


void solve()
{
    int n, m;
    cin >> n >> m;
    uf (i, 1, n) cin >> mp[i] + 1;
    int lx = INT_MAX, ly = lx, rx = 0, ry = 0;
    uf (i, 1, n)
    {
        uf (j, 1, m)
        {
            if (mp[i][j] == '#')
            {
                lx = min(i, lx);
                ly = min(j, ly);
                rx = max(i, rx);
                ry = max(j, ry);
            }
        }
    }
    uf (i, lx, rx) uf (j, ly, ry) 
    {
        if (mp[i][j] == '.') cout << i << " " << j << endl;
    }
}

signed main()
{
    freopen("C:\\Users\\swk\\Desktop\\Problems\\.in", "r", stdin);
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    int t = 1;
    // cin >> t;
    while (t --) solve();
    return 0;
}

D - Sleep Log

题目
奇数长度的序列,奇数位是开始醒着的时刻,偶数位是开始睡眠的时刻,首个元素为0,给Q个询问,每次询问一个区间,问该区间内的总的睡眠时间

  • 前缀和,统计当前位置总共的睡眠时间
  • 对于每个查询的区间,都用二分去查找属于哪个区间,如果处于偶数位区间,那么需要减去区间两侧的睡眠时间
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
#define x first
#define y second
#define INF 0x3f3f3f3f
#define vi vector<int>
#define pii pair<int, int>
#define mset(x, v) memset(x, v, sizeof x)
#define all(x) ((x).begin()), ((x).end())
#define uf(i, j, k) for (int i = j; i <= k; i ++)
#define df(i, j, k) for (int i = j; i >= k; i --)

using namespace std;
const int N = 2e5 + 5;
int a[N], s[N], p[N];
void solve()
{
    int n;
    cin >> n;
    uf (i, 1, n) cin >> a[i];
    uf (i, 1, n)
    {
        if (i % 2 == 0) s[i] = s[i - 1] + a[i + 1] - a[i];
        else s[i] = s[i - 1];
    }

    int q;
    cin >> q;
    while (q --)
    {
        int ll, rr;
        cin >> ll >> rr;
        int l = 1, r = n;
        while (l < r) 
        {
            int mid = l + r + 1 >> 1;
            if (a[mid] <= ll) l = mid;
            else r = mid - 1;
        }
        int x = l;
        l = 1, r = n;
        while (l < r) 
        {
            int mid = l + r + 1 >> 1;
            if (a[mid] <= rr) l = mid;
            else r = mid - 1;
        }
        int y = l;
        int ans = s[y] - s[x - 1];
        if (y % 2 == 0) ans -= a[y + 1] - rr;
        if (x % 2 == 0) ans -= ll - a[x];
        cout << ans << endl;
    }
}

signed main()
{
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    int t = 1;
    // cin >> t;
    while (t --) solve();
    return 0;
}

E - Art Gallery on Graph

题目
给一个G(n,m) 无向图,有k个保安分散在这些结点,每个保安的监视范围为hi,只有结点到保安所在的结点最短边数不超过 其监视范围才能被称为安全结点,升序输出安全结点

  • 一开始想的是超级源点,但是这里是保安结点到其他结点的最短距离,如果是其他结点到保安结点的最短距离还可以用
  • 但是进而想到是可以分别从保安结点开始走,直到不能走为止,用优先队列优化一下
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
#define x first
#define y second
#define INF 0x3f3f3f3f
#define vi vector<int>
#define pii pair<int, int>
#define mset(x, v) memset(x, v, sizeof x)
#define all(x) ((x).begin()), ((x).end())
#define uf(i, j, k) for (int i = j; i <= k; i ++)
#define df(i, j, k) for (int i = j; i >= k; i --)

using namespace std;
const int N = 2e5 + 5, M = N << 1;
int n, m, k, idx = 0;
int f[N], ne[M], e[M], w[M], dist[N];
bool st[N];
void add(int a, int b, int c)
{
    w[idx] = c;
    e[idx] = b;
    ne[idx] = f[a];
    f[a] = idx ++;
}

void solve()
{
    cin >> n >> m >> k;
    mset(f, -1);
    mset(dist, -1);
    while (m --) 
    {
        int a, b;
        cin >> a >> b;
        add(a, b, 1);
        add(b, a, 1);
    }
    priority_queue<pii> q;
    uf (i, 1, k) 
    {
        int p, h;
        cin >> p >> h;
        dist[p] = h;
        q.push({dist[p], p});
    }

    while (q.size()) 
    {
        auto u = q.top().y;
        q.pop();
        for (int i = f[u]; ~i; i = ne[i]) 
        {
            int v = e[i];
            if (dist[v] < dist[u] - 1)
            {
                dist[v] = dist[u] - 1;
                q.push({dist[v], v});
            }
        }
    }
    vector<int> ans;
    uf (i, 1, n) 
    {
        if (dist[i] >= 0) ans.push_back(i);
    }   
    cout << ans.size() << endl;
    for (auto x : ans) cout << x << " ";

} 

signed main()
{
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    int t = 1;
    // cin >> t;
    while (t --) solve();
    return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值