Codeforces Round #731 (Div. 3)

本文详细介绍了四种算法问题的解决思路,包括直线上的最短路径计算,考虑障碍因素;字母字符串的排序检查;配对编程中的0元素处理;以及序列的二进制增长规律。通过实例解析,阐述了每种问题的解决策略,涉及贪心算法、二进制操作和动态规划等思想。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

A - Shortest Path with Obstacle

思路

在一条直线上,且在起点和终点之间就绕路

#include <iostream>
#include <cmath>
#include <algorithm>
 
using namespace std;
 
int main ()
{
    int t;
    cin >> t;
    while (t --)
    {
        int xa, xb, xf, ya, yb, yf;
        cin >> xa >> ya >> xb >> yb >> xf >> yf;
        if (xa == xb && xa != xf)
            cout << abs (ya - yb) << endl;
        else if (ya == yb && ya != yf)
            cout << abs (xa - xb) << endl;
        else if (xa == xb && (xa == xf && min (ya, yb) < yf && max (ya, yb) > yf))
            cout << abs (ya - yb) + 2 << endl;
        else if (ya == yb && (ya == yf && min (xa, xb) < xf && max (xa, xb) > xf))
            cout << abs (xa - xb) + 2 << endl;
        else 
            cout << abs (xa - xb) + abs (ya - yb) << endl;
    }
}

B - Alphabetical Strings

思路

找到a,前面递减,后面递增,再判断排序完了的结果是否缺字母

#include <iostream>
#include <string>
#include <algorithm>
 
using namespace std;
 
int a[30];
 
int main ()
{
    int t;
    cin >> t;
    int b[30];
    for (int i = 0; i < 26; i ++)
        b[i] = i;
    while (t --)
    {
        string tmp;
        int flag = -1, maxx = -1;
        bool f = true;
        cin >> tmp;
        for (int i = 0; i < tmp.length (); i ++)
        {
            a[i] = tmp[i] - 'a';
            if (a[i] == 0)
                flag = i;
            if (a[i] > maxx)
                maxx = a[i];
        }
        // cout << " <<<< " << flag << endl;
        // cout << " <<<< " << maxx << endl;
        if (flag == -1)
            f = false;
        else if (flag == 0 && tmp.length () == 1)
            f = true;
        else 
        {
            if (maxx != tmp.length () - 1)
                f = false;
            for (int i = 0; i < flag; i ++)
            {
                if (a[i] <= a[i + 1])
                {
                    f = false;
                }
            }
            for (int i = flag; i < tmp.length () - 1; i ++)
            {
                if (a[i] >= a[i + 1])
                {
                    f = false;
                }
            }
            sort (a, a + tmp.length ());
            for (int i = 0; i < tmp.length (); i ++)
                if (a[i] != b[i])
                    f = false;
        }
        if (f) cout << "YES" << endl;
        else 
            cout << "NO" << endl;
        
    }
}

C - Pair Programming

思路

有0先放0,没0判断这行存在不存在

#include <iostream>
 
using namespace std;
 
int main ()
{
    int t;
    cin >> t;
    while (t --)
    {
        int k, n, m, x = 0;
        int a[110], b[110], ans[220];
        bool f = 0;
        cin >> k >> n >> m;
        for (int i = 1; i <= n; i ++)
            cin >> a[i];
        for (int i = 1; i <= m; i ++)
            cin >> b[i];
        int na = 1, nb = 1;
        while (1)
        {
            if (na == n + 1 && nb == m + 1) f = 1;
            if (a[na] <= k && na <= n)
            {
                ans[na + nb - 1] = a[na];
                if (a[na] == 0) k ++;
                na ++;
                continue;
            }
            if (b[nb] <= k && nb <= m)
            {
                ans[na + nb - 1] = b[nb];
                if (b[nb] == 0) k ++;
                nb ++;
                continue;
            }
            break;
        }
        if (f)
        {
            for (int i = 1; i <= n + m; i ++)
                cout << ans[i] << " ";
            cout << endl;
        }
        else 
            cout << -1 << endl;
    }
}

D - Co-growing Sequence

题目大意

给你一个序列x,让你寻找一个最小的序列y,使得x[i] ^= y[i],x[i] & x[i + 1] = x[i]

思路

二进制表示下a[i]的第k位为1,则a[i+1]第k位也必须为1,且维护一个当前最大值x。
这样的话,如果a[i + 1]的第k位为0,而a[i]的第k位为1,要把a[i + 1]的第k位变为1。对a[i + 1]按位取反后,~a[i+1]的第k位为1,此时x & ~a[i + 1]的第k位就为1,原本a[i + 1]中为1的,就会变成0,不需要加,根据二进制的加法法则,可知需要加上的数tmp便为x & ~a[i + 1]。
然后再更新x,x = a[i] ^tmp(或x = a[i] + tmp)便为当前最大值,即改变后的a[i + 1]

例如:a[i] = 1101, a[i + 1] = 1011, 此时a[i + 1]第2位不为1,但a[i]第2位为1,所以要给a[i + 1]加上100,使其变为1011 + 100 = 1111,其中100便为1101 & ~1011 = 1101 & 100 = 100。

#include <iostream>

using namespace std;

const int N = 2e5 + 10;

int a[N];

int main ()
{
    int t;
    cin >> t;
    while (t --)
    {
        int n;
        cin >> n;
        int x = 0;
        for (int i = 1; i <= n; i ++)
        {
            cin >> a[i];
            int tmp = x & (~a[i]);
            cout << tmp << " ";
            x = a[i] ^ tmp; // 或 x = a[i] + tmp;
        }
        cout << endl;
    }
}

题目大意

每个格子i的温度,是空调温度,加上空调离格子i的距离的最小值,即
m i n 1 ≤ j ≤ k ( t j + ∣ a j − i ∣ ) min_{1≤j≤k}(t_j+|a_j−i|) min1jk(tj+aji)
求每个格子的空调温度

思路

贪心,从前往后跑一遍,从后往前跑一遍,取最小即可。

#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

typedef long long ll;

int main ()
{
    int q;
    cin >> q;
    while (q --)
    {
        int n, k;
        cin >> n >> k;
        vector <int> a (k);
        for (int i = 0; i < k; i ++)
            cin >> a[i];

        vector <int> t (k);
        for (int i = 0; i < k; i ++)
            cin >> t[i];

        vector <ll> c (n, INT_MAX);
        for (int i = 0; i < k; i ++)
            c[a[i] - 1] = t[i];

        ll p;
        vector <ll> L (n, INT_MAX);
        p = INT_MAX;
        for (int i = 0; i < n; i ++)
        {
            p = min (p + 1, c[i]);
            L[i] = p;
        }

        vector <ll> R (n, INT_MAX);
        p = INT_MAX;
        for (int i = n - 1; i >= 0; i --)
        {
            p = min (p + 1, c[i]);
            R[i] = p;
        }

        for (int i = 0; i < n; i ++)
            cout << min (L[i], R[i]) << " ";
        cout << endl;
    }
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值