【cf】CodeForces Round 886(Div.4)题解

A. To My Critics

题意

签到题,问输入的三个数里较大两数之和是否大于等于10

思路

存进数组然后排序,取较大的两个数相加和10比较

代码

#include 

using namespace std;

int main()
{
    int t; cin >> t;
    while (t -- )
    {
        int a[3];
        cin >> a[0] >> a[1] >> a[2];
        sort(a, a + 3);
        if (a[1] + a[2] >= 10) cout << "YES\n";
        else cout << "NO\n";
    }
}

B. Ten Words of Wisdom

题意

每组输入两个数,判断在第一个数小于等于10的情况下,最大的第二个数的序号

思路

vector>存数据,first存第二个输入的数,second存输入序号,当第一个数小于等于10时就将其存入,然后对vector排序,输出最大的第二个数的编号

代码

#include 

using namespace std;

typedef pair<int, int> PII;

int main()
{
    int t;
    cin >> t;
    while (t -- )
    {
        int n;
        cin >> n;
        vector<PII> a;
        for (int i = 0; i < n; i ++ )
        {
            int x;
            int y;
            cin >> x >> y;
            if (x <= 10) a.push_back(make_pair(y, i));
        }
        sort(a.begin(), a.end());
        cout << a[a.size() - 1].second + 1 << endl;
    }
}

C. Word on the Paper

题意

8x8的矩阵中,输出所有竖着排列的字符串

思路

遍历整个矩阵,遇到非.时就将其和下方的所有非.元素输出

代码

#include 

using namespace std;

const int N = 8010;

char grid[N][8];
bool st[8];

int main()
{
    int t;
    cin >> t;
    while (t -- )
    {
        memset(st, false, sizeof st);
        for (int j = 0; j < 8; j ++ )
           for (int k = 0; k < 8; k ++ )
                cin >> grid[j][k];
        for (int i = 0; i < 8; i ++ )
            for (int j = 0; j < 8; j ++ )
                if (grid[i][j] != '.' && !st[j])
                {
                    int h = i;
                    st[j] = true;
                    while (h < 8)
                    {
                        if (grid[h][j] != '.') cout << grid[h][j];
                        h ++ ;
                    }
                    cout << '\n';
                }
    }
}

D. Balanced Round

题意

给出一串数字,可以任意交换他们的位置,要求删掉最小个数的数字,让连续的两个数字差值小于给定的 k

思路

先从大到小排序,用dp做,f[i][j]表示在前 i 个数字内能选择的最大个数,j 表示第 i 个数有没有选,1表示选了,0表示没选,从前往后更新f[i][j]f[n][1]f[n][0]的较大值为能选择的最大数字个数,用总个数减去最大个数就是删去的最小个数

代码

#include 

using namespace std;

const int N = 200010;

int f[N][2];

int main()
{
    int t;
    cin >> t;
    while (t -- )
    {
        int n, k;
        cin >> n >> k;
        vector<int> a(n);
        for (int i = 0; i < n; i ++ ) cin >> a[i];
        sort(a.begin(), a.end());
        f[0][0] = 0;
        f[0][1] = 1;
        for (int i = 1; i < n; i ++ )
        {
            if (a[i] - a[i - 1] <= k)
            {
                f[i][1] = f[i - 1][1] + 1;
                f[i][0] = max(f[i - 1][0], f[i - 1][1]);
            }
            else
            {
                f[i][1] = 1;
                f[i][0] = max(f[i - 1][0], f[i - 1][1]);
            }
        }
        int ans = max(f[n - 1][1], f[n - 1][0]);
        cout << n - ans << '\n';
    }
}

E. Cardboard for Pictures

题意

有一组已知边长的正方形,现在要将每个正方形的边长加上同一个w,问w是多少能满足所有新正方形的面积等于给定值c

思路

一开始路走歪了…不知道怎么就去解一元二次方程去了,然后因为double的误差wa了
实际很简单~ 二分就可以啦~
首先利用倍增思想,把每个正方形边长都加上 2j,求出最小的 j 使总面积第一次大于 c
然后就在1到 j 之间二分求出 w

代码

#include 

using namespace std;

using i64 = unsigned long long;

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    
    int t;
    cin >> t;
    while (t -- )
    {
        i64 n, sum;
        cin >> n >> sum;
        vector<i64> a(n);
        for (int i = 0; i < n; i ++ ) cin >> a[i];

        i64 l = 0, r = 1;
        while (1)
        {
            i64 res = 0;
            for (int i = 0; i < n; i ++ ) res += (a[i] + 2 * r) * (a[i] + 2 * r);
            if (res >= sum) break;
            r *= 2;
        }

        while (l < r)
        {
            i64 mid = l + r >> 1;
            i64 res = 0;
            for (int i = 0; i < n; i ++ ) res += (a[i] + 2 * mid) * (a[i] + 2 * mid);
            if (res >= sum) r = mid;
            else l = mid + 1;
        }
        cout << r << '\n';
    }
}

F. We Were Both Children

题意

每个青蛙都可以跳到它弹跳能力的整数倍上,人能到达的最远距离是青蛙的个数,现在人要待在一个位置逮青蛙,问待在那个位置逮到的青蛙最多

思路

先标记每个青蛙第一次跳到的位置,之后从后往前更新每个青蛙能跳到的小于 n 的位置,选择有最多青蛙能跳到的位置输出

代码

#include 

using namespace std;

const int N = 200010;

int main()
{
    int t;
    cin >> t;
    while (t -- )
    {
        int n;
        cin >> n;
        vector<int> a(n);
        vector<int> cnt(n + 1);
        for (int i = 0; i < n; i ++ )
        {
            cin >> a[i];
            if (a[i] <= n) cnt[a[i]] ++ ;
        }
        for (int i = n; i >= 1; i -- ) // 从大到小遍历是为了防止前面的更新对后面产生影响
            for (int j = i * 2; j <= n; j += i)
                cnt[j] += cnt[i];

        cout << *max_element(cnt.begin(), cnt.end()) << '\n';
    }
}

G. The Morning Star

题意

从所有给的坐标里面选择两个坐标,一个放a,一个放b,这两个坐标要在同一条直线上

思路

遍历给定的坐标,只要这个坐标同一行 / 同一列 / 对角线 / 反对角线上有坐标,这个坐标就是可以选的,所以只要判断上面列举的四种情况有没有对应的坐标,有就加上,之后再更新遍历到的这个点
最后不要忘记*2,因为ab可以交换

代码

#include 

using namespace std;

using i64 = long long;

typedef pair<int, int> PII;

int main()
{
    int t;
    cin >> t;
    while (t -- )
    {
        int n;
        cin >> n;
        map<i64, int> a; // 横
        map<i64, int> b; // 竖
        map<i64, int> c; // 对角线
        map<i64, int> d; // 反对角线
        i64 ans = 0;
        for (int i = 0; i < n; i ++ )
        {
            i64 x, y;
            cin >> x >> y;
            ans += a[x] + b[y] + c[x - y] + d[x + y];
            a[x] ++ ;
            b[y] ++ ;
            c[x - y] ++ ;
            d[x + y] ++ ;
        }

        cout << ans * 2 << '\n';
    }
}

H. The Third Letter

题意

给定士兵个数和信息条数,每条信息告诉两个士兵的相对位置,判断所有的信息是否矛盾

思路

把和每个点有关的信息存到vector>里面,存完后逐个士兵dfs判断是否矛盾

代码

#include 

using namespace std;

const int N = 200010;

using i64 = long long;
typedef pair<int, int> PII;

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);

    int t;
    cin >> t;
    while (t -- )
    {
        int n, q;
        cin >> n >> q;

        vector<i64> d(n + 1);
        vector<bool> st(n + 1);
        bool flag = true;
        vector<vector<PII>> g(n + 1);

        while (q -- )
        {
            int a, b, c;
            cin >> a >> b >> c;
            g[a].push_back(make_pair(b, c));
            g[b].push_back(make_pair(a, -c));
        }

        function<void(int)> dfs = [&](int u)
        {
            st[u] = true;
            for (int i = 0; i < g[u].size(); i ++ )
            {
                int j = g[u][i].first;
                int w = g[u][i].second;
                if (!st[j])
                {
                    d[j] = d[u] + w;
                    dfs(j);
                }
                else if (d[j] != d[u] + w) flag = false;
            }
        };

        for (int i = 1; i <= n; i ++ )
            if (!st[i]) dfs(i);

        if (!flag) cout << "NO\n";
        else cout << "YES\n";
    }
}

你可能感兴趣的:(Codeforces,题解,c++,算法)