Codeforces Round 860 (Div. 2)

Codeforces Round 860 (Div. 2)

Date: 04/08/2023

Link: Codeforces Round 860 (Div. 2)

A|Showstopper

Brief: 两组数 {ai}{bi},长度都为 n. i , 可以交换 aibi, 问是否可以使得 an=max(ai), bn=max(bi).

Data: T200, n100.

Solution: 【简单思维题】

发现只需考虑当把大的放在一边,小的放在另一边时的可行性。

题解提到一个比较重要的思想:交换操作大于等于 2 时是无效的。

Complexity: O(Tn).

Review: -

State: AC.

Code:

#define Justanaaaaame
#include <cstdio>
#include <iostream>
using namespace std;

#define MAXN 110

int main()
{
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    int T;
    cin >> T;
    while (T--)
    {
        int n;
        cin >> n;
        int a[MAXN], b[MAXN];
        for (int i = 1 ; i <= n ; ++i)
            cin >> a[i];
        for (int i = 1 ; i <= n ; ++i)
            cin >> b[i];
        for (int i = 1 ; i <= n ; ++i)
            if (a[i] < b[i])
                swap(a[i], b[i]);
        bool flag = true;
        for (int i = 1 ; i < n ; ++i)
            if (a[i] > a[n] || b[i] > b[n])
            {
                flag = false;
                break;
            }
        if (flag)
            cout << "Yes\n";
        else
            cout << "No\n";
    }
}

B|Three Sevens

Brief: m 天,每天 ni 人参加比赛,编号分别为 ai,j. 每天有一个胜者,胜者在之后的比赛中不出现。构造出一个可能的胜者序列。

Data: T50000, m50000, ni50000.

Solution: 【简单思维题】【构造】

一个比较重要的思想:倒序考虑。

倒序维护出现过的人,在每一天找一个没出现过的人即可。

Review: 实现时在循环里声明大数组TLE,放全局变量AC:声明有复杂度QAQ(滚去学 cpp 惹~

State: AC.

Code:

#define Justanaaaaame
#include <iostream>
#include <vector>
#include <cstring>
using namespace std;

#define MAXN 50010

vector <int> v[MAXN];
bool vis[MAXN];
int ans[MAXN];

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

    int T;
    cin >> T;
    while (T--)
    {

        int m;
        cin >> m;
        for (int i = 1 ; i <= m ; ++i)
        {
            v[i].clear();
            int n;
            cin >> n;
            for (int j = 1 ; j <= n ; ++j)
            {
                int t;
                cin >> t;
                v[i].push_back(t);
                vis[t] = false;
            }
        }
        bool flag;
        for (int i = m ; i ; --i)
        {
            flag = false;
            for (const auto &x : v[i])
                if (!vis[x])
                {
                    vis[x] = true;
                    ans[i] = x;
                    flag = true;
                }
            if (!flag)
                break;
        }
        if (flag)
        {
            for (int i = 1 ; i <= m ; ++i)
                cout << ans[i] << ' ';
            cout << "\n";
        }
        else
        {
            cout << "-1\n";
        }
    }

    return 0;
}

C|Candy Store

Brief: n 种糖,第 i 种有 ai 颗,每颗 bi 元。现在把第 i 种糖分成 ai/di 袋,每袋 di 颗,那么一袋 c=bidi 元。一个标签可以覆盖相邻价格一样的糖果袋,求在不改变糖的顺序的前提下,最少的标签数量。

Data: T100000, 2n200000, ni20000.

Solution: 【数学】

Observation 1: 贪心地让当前的标签覆盖更多的袋子最优;

Observation 2: bic. 对于一个标签覆盖的,lcm(bi)c;

Observation 3: caibi (由于 c(ai/di)=aibi). 对于一个标签覆盖的,cgcd(aibi);

综上,只需从前往后判断新加入的是否满足 lcm(bi)gcd(aibi), 不满足则新加一个标签。

Review: 实际上离结论已经很近了,然而……

State: -> AC.

Code:

#define Justanaaaaame
#include <iostream>
using namespace std;
#define int long long

int gcd(int a, int b)
{
    while(a ^= b ^= a ^= b %= a);
    return b;
}

int lcm(int a, int b)
{
    return a * b / gcd(a, b);
}

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

    int T;
    cin >> T;
    while (T--)
    {
        int n;
        cin >> n;
        int ans = 1;
        int a1, b1;
        cin >> a1 >> b1;
        int g = a1 * b1, l = b1;
        for (int i = 2 ; i <= n ; ++i)
        {
            int a, b;
            cin >> a >> b;
            g = gcd(g, a * b);
            l = lcm(l, b);
            if (g % l)
            {
                ++ans;
                g = a * b;
                l = b;
            }
        }
        cout << ans << '\n';
    }
}

D|Shocking Arrangement

Brief: 给定整数序列,满足和为 0。需要构造一个排列,使得 max1lrn|al+al+1++ar|<max(a)min(a).

Data: T50000, 1n300000, ni30000.

Solution: 【构造】【dp】

Observation 1: 左式可以写成 maxPrefSumminPrefSum

Observation 2: 只需满足 maxPrefSummax(a) and minPrefSummin(a) 且不能同时取等。

综上,只需当前缀和 >0 时,放一个小于 0 的数;在前缀和 0 时,放一个 0 的数。如此构造前缀和一定在最大值和最小值之间。

另外,注意到全为 0 时取等,无解。

Review: 关键在于公式的转换。注意max和min的性质。复健基本模型。

State: AC.

Code:

#define Justanaaaaame
#include <iostream>
using namespace std;

#define MAXN 300010
int np, pos[MAXN];
int nn, neg[MAXN];

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

    int T;
    cin >> T;
    while (T--)
    {
        nn = 0;
        np = 0;
        int n;
        cin >> n;
        for (int i = 1 ; i <= n ; ++i)
        {
            int t;
            cin >> t;
            if (t >= 0) pos[++np] = t;
            else        neg[++nn] = t;
        }
        if (nn == 0)
        {
            cout << "No\n";
            continue;
        }
        cout << "YES\n";
        long long prefsum = 0;
        for (int i = 1 ; i <= n ; ++i)
        {
            if (prefsum > 0)
            {
                prefsum += neg[nn];
                cout << neg[nn--] << ' ';
            }
            else
            {
                prefsum += pos[np];
                cout << pos[np--] << ' ';
            }
        }
        cout << '\n';
    }

    return 0;
}

E|Multitest Generator

Brief: 定义test: 数列的第一个数是长度-1,multitest: 数列第一个数是能将后面的数划分成test的数量。给出一列数,问对于 i[1,n1] ,最少修改多少个数使得数列 {ai,ai+1,,an} 为 multitest.

Data: T300000, 2n300000, ni30000.

Solution: 【dp】

Observation 1: 答案只可能是 0,1,2, 这一点可以从样例得到启发。原因是只需要修改第一个数为 1, 第二个数为 n2 则一定可以使其成为 multitest;

Observation 2: 判断为 0 是容易的,从后往前考虑,同时维护链(test)是否能覆盖完整个序列,如果可以,计算链的长度。假如可以覆盖并且 ai 等于test的个数, 那么答案为 0.

Observation 3: 现在只需要考虑何时为 1.

​ (1) 可以覆盖,则只需更改第一个数为test数量;

​ (2) 不能覆盖,那么只需求出最大可能的test数,小于该值的也一定可行,因为可以修改第二个值,使得其多覆盖任意多个test。那么问题变为如何计算修改一次后最大可能的test数。考虑 dp,如果修改第二个数,test数量为之后可覆盖的最长链+1;如果不修改第二个数,答案为 dp[a[i] + i + 1] + 1.取 max 即可。和第一个数比较大小,若第一个数小于等于这个数,那么答案为 1,否则为 2.

Review: -

State: AC.

Code:

#define Justanaaaaame
#include <iostream>
#include <cstring>
using namespace std;

#define MAXN 300010
int a[MAXN];
int go[MAXN];
bool able[MAXN];
int len[MAXN];
int dp[MAXN];   // 第 i 位后修改1次的最长链
int ans[MAXN];

int main()
{
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    
    int T;
    cin >> T;
    while (T--)
    {
        int n;
        cin >> n;
        memset(able, 0, sizeof(bool) * (n+5));
        memset(len, 0, sizeof(int) * (n+5));
        memset(dp, 0, sizeof(int) * (n+5));
        for (int i = 1 ; i <= n ; ++i)
        {
            cin >> a[i];
            go[i] = i + a[i] + 1;
            if (go[i] > n + 1)
                go[i] = n + 2;
        }
        able[n + 1] = true;
        int maxlen = 0;    
        for (int i = n ; i ; --i)
        {
            able[i] = able[go[i]];
            len[i] = len[go[i]] + 1;
            if (able[i])
                maxlen = max(maxlen, len[i]);
            dp[i] = max(dp[go[i]] + 1, maxlen + 1);
        }
        for (int i = n - 1 ; i ; --i)
        {
            if (able[i + 1])
            {
                if (a[i] == len[i + 1])
                    ans[i] = 0;
                else
                    ans[i] = 1;
            }
            else
            {
                if (dp[i + 1] >= a[i])
                    ans[i] = 1;
                else
                    ans[i] = 2;
            }
        }
        for (int i = 1 ; i < n ; ++i)
            cout << ans[i] << ' ';
        cout << '\n';
    }

}

F|Gifts from Grandfather Ahmed

State: 咕咕咕

posted @   Justanaaaaame  阅读(41)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· Apache Tomcat RCE漏洞复现(CVE-2025-24813)
点击右上角即可分享
微信分享提示