Codeforces Round #763 (Div. 2)(A-C)

题目

A - Robot Cleaner

题意:给定n × m的区间,然后给定机器人和目标的坐标,然后机器人起初往右下方走,碰到墙壁就会改变方向,类似于折射,然后问在最短走几步能移动到到目标的行或者是列。
思路:模拟,可以分为两个方向进行讨论,水平和垂直方向,如果目标在某一个方向的正方向的话,那么最短距离就是这个方向的距离差,否则就是(n - x) + (m - y),其实这个也不难理解,看看所给的图找找规律就好。

AC code
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

int n, m, ex, ey, bx, by, d;
int ans = 0x3f3f3f3f;

int main()
{
    int t;
    cin >> t;
    while(t -- )
    {
        ans = 0x3f3f3f3f;
        cin >> n >> m >> bx >> by >> ex >> ey;

        if(ex == bx || ey == by) puts("0");
        else
        {
            if(ex < bx)
            {
                int x = (n - ex) + (n - bx);
                ans = min(ans, x);
            }
            else
                if(ex > bx)
                {
                    ans = min(ans, (ex - bx));
                }
            if(ey < by)
            {
                int x = (m - ey) + (m - by);
                ans = min(x, ans);
            }
            else
                if(ey > by)
                {
                    ans = min(ans, ey - by);
                }
                cout << ans << endl;
        }

        
    }

    return 0;
}
B - Game on Ranges

题意:Alice 选择一个区间,然后让Bob来选择一个数,比如Alice选择一个1-5的区间,Bob选择3,那么就会分成两个小区间1 - 2和4 - 5,或者是选择4,那么只剩下1 - 3和5 - 5两个区间,现在给你Alice选择的区间,然后让你写出Bob在Alice所给的区间种选择的哪个数,起初的区间是1 ~ n。
思路:模拟,可以将区间根据区间长度来进行升序排序,从最小的开始处理,区间种肯定存在着长度为1的区间,将这些单独的区间进行标记,然后可解决区间长度为2,最后解决最后的大区间。例如样例
1 5
1 2
4 5
2 2
4 4
先处理4和2,然后到4-5这个区间,4肯定是最后处理的,所以4-5这个区间选择的是5,同理1-2选择的是1,那么最后的1-5区间,其他的数已经选择完,那么只能选择3。

AC code
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 5010;

struct ll
{
    int l, r, len, c;
}L[N];

int n;
int sta[N];

bool cmp(ll a, ll b)
{
    return a.len < b.len;
}

int main()
{
    int t;
    cin >> t;

    while(t -- )
    {
        cin >> n;

        memset(sta, 0, sizeof(sta));
        memset(L, 0, sizeof(L));

        for(int i = 1; i <= n; i ++)
        {
            int a, b;
            cin >> a >> b;

            L[i] = {a, b, b - a, 0};
        }

        sort(L + 1, L + 1 + n, cmp);

        for(int i = 1; i <= n; i ++)
        {
            if(L[i].l == L[i].r)
            {
                sta[L[i].r] = 1;
                L[i].c = L[i].l;
            }
            else
            {
                for(int j = L[i].l; j <= L[i].r; j ++)
                {
                    if(!sta[j])
                    {
                        L[i].c = j;
                        sta[j] = 1;
                    }
                
                }
            }
        }

        for(int i = 1; i <= n; i ++)
        {
            cout << L[i].l << ' ' << L[i].r << ' ' << L[i].c << endl;
        }
        puts("");
    }
    
    return 0;
}

C - Balanced Stone Heaps

题意:给定一个序列,可以执行此操作,选择一个数 d ,然后将当前这个位置n的数取出 d 加到n - 1的位置,然后取出2 × d 加到n - 2的数上,0 ≤ d ≤ a[n],让坐标大于等于3的数都执行这一个操作,问最小的数最大时多少。
思路:二分,将答案进行二分,要注意的是,我们判断时候是从后往前进行此过程,但是实际上我们是从前往后进行此过程,所以一定要注意不能 d 不能大于当前数的三分之一,这个是最重要的。

AC code
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 2e5 + 10, INF = 0x3f3f3f3f;

int n;
int a[N], b[N];

bool check(int mid)
{
    for(int i = 1; i <= n; i ++)
    {
        b[i] = a[i];
    }

    for(int i = n; i >= 3; i --)
    {
        if(b[i] < mid) return false;

        int x = min((b[i] - mid) / 3, a[i] / 3);

        //if(b[i] - 3 * x < mid) return true;

        //b[i] -= 3 * x;
        b[i - 1] += x;
        b[i - 2] += 2 * x;
    }

    if(b[1] >= mid && b[2] >= mid) 
        return true;
    return false;

}

int main()
{
    int t;
    scanf("%d", &t);

    while(t -- )
    {
        scanf("%d", &n);

        int mx = -INF, mi = INF;
        for(int i = 1; i <= n; i ++) 
        {
           scanf("%d", &a[i]);

            mx = max(mx, a[i]);
            mi = min(mi, a[i]);
        }

        int l = mi, r = mx;

        //cout << l << ':' << r << endl;

        while (l < r)
        {
            int mid = (l + r + 1) >> 1;	//(l+r+1)/2

            if (check(mid))  
                l = mid;
            else 
                r = mid - 1;
        }

        printf("%d\n", l);
    }

    return 0;
}
感悟

前两个题还好,第三个题说实话是没有发现是二分,当发现最小值最大这个字眼二分就跑不了了,然后还有注意的是,二分的时候可以先把check函数写出,因为其中返回的时候要根据题意进行返回,暴不能根据你写的二分的分法来决定,二分的方式要根据check条件来决定。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值