Codeforces Round 839 (Div. 3) vp总结

小菜鸡的VP总结

C. Different Differences

  • 题意:包含k个整数的数组a,是严格单调递增的,定义“特征”为a中元素两两相减后所构成数组[a2-a1,a3-a2,...,ak-a(k-1)]中不同的数字个数。给出一个k和n你需要构造出一个最大“特征”数的数组a,其中数字只能在1-n的范围内。
  • 思路:观察样例可以发现将a元素中的元素两两相减后所构成的数组加起来即为n,所以可以将1和n放在首位和末位,计算除去它们的差值,并按照+1 +2 +3的方式,构造第二位第三位第四位...而后将不足的+1即可
void BlueFire()
{
    int k, n;
    cin >> k >> n;
    int x = n - 1;
    vector<int> v(k + 1);
    v[1] = 1;
    v[k] = n;
    for (int i = 2; i <= k - 1; i++)
        v[i] = 1;
    int cz = x - (k - 2);
    int lstIndex = -1; 
    for (int i = 2, j = 1; i <= k - 1; i++)
    {
        if (cz < j)
        {
            lstIndex = i;
            break;
        }
        v[i] = v[i - 1] + j;
        cz -= j;
        j++;
    }
    if (lstIndex != -1)
        for (int i = lstIndex; i <= k - 1; i++)
            v[i] = v[i - 1] + 1;

 
    for (int i = 1; i <= k - 1; i++)
        cout << v[i] << " ";
    cout << v[k] << endl;
 
    return;
}

D. Absolute Sorting

  • 题意:给出一个包含n个整数的a数组,当数组呈递增时视为已排序。执行一次操作:选择一个数x,将数组里的每个数都替换为这个数和x做差的绝对值,找出可以让a数组排序的x。
  • 思路:观察后发现这个x应该是非递增的两个相邻数加起来除以2向上取整,然后取最大值,当然要注意找到x后还要计算一遍,如果不符合就要输出-1(无法排序)
void BlueFire()
{
    int n;
    cin >> n;
    vector<ll> v(n + 1);
    for (int i = 1; i <= n; i++)
        cin >> v[i];
    ll minn = 0;
    for (int i = 1; i <= n - 1; i++)
    {
        if (v[i] > v[i + 1])
        {
            ll x = ((v[i + 1] + v[i]) % 2 == 0 ? (v[i + 1] + v[i]) / 2 : (v[i + 1] + v[i]) / 2 + 1);
            if (x > minn)
                minn = x;
        }
    }
    for (int i = 1; i <= n; i++)
        v[i] = abs(v[i] - minn);
    for (int i = 1; i <= n - 1; i++)
        if (v[i] > v[i + 1])
        {
            cout << -1 << endl;
            return;
        }
 
    cout << minn << endl;
 
    return;
}

E. Permutation Game

  • 题意:两个玩家玩一个游戏,给出一组包含n个数字的排列,所有的数字一开始都是红色,每名玩家可以执行三种操作:
    1.重新排列蓝色的数字
    2.将一个红色的数字变为蓝色
    3.跳过本回合
    先手的获胜条件是这个排列变为升序排列,后手的获胜条件是变为降序排列,你需要给出最后获胜的玩家
  • 思路:假设是先手,要变为升序排列(1,2...n),那么对应位置上的数如果不是升序排列的数,为了获胜先手一定会将其变为蓝色(为了把那个正确的数交换过来),同理后手也是,对自己最优的策略一定是先将不符合降序的数变为蓝色再交换,因此我们要计算先手和后手一定要变色的数然后比对即可,如果都不属于两种情况,就是需要拿来交换的数字,也要计算。注意平局的情况。
void BlueFire()
{
    int n;
    cin >> n;
    vector<int> v(n + 1);
    for (int i = 1; i <= n; i++)
        cin >> v[i];
    int cnt1 = 0, cnt2 = 0, cnt = 0;
    for (int i = 1; i <= n; i++)
    {
        if (v[i] == i)
            cnt2++;
        else if (v[i] == n - i + 1)
            cnt1++;
        else
            cnt++;
    }

    if (cnt1 + cnt <= cnt2)//先手所以有等号
        cout << "First" << endl;
    else if (cnt2 + cnt < cnt1)
        cout << "Second" << endl;
    else
        cout << "Tie" << endl;

    return;
}

F. Copy of a Copy of a Copy

  • 题意:给出一个n*m的01矩阵,每次可以进行如下操作:选择一个位置,该位置四个方向的01情况与该位置不同,将该位置01变换,创建改变后的拷贝矩阵。现在给出k个拷贝矩阵和原矩阵,但是顺序并不是按照操作顺序的,现在需要找出初始矩阵,并输出操作方案。
  • 思路:能修改的地方最多的一定是最初的,根据这种规则排序,依次比较不同的地方即可
int dx[4] = {1, -1, 0, 0};
int dy[4] = {0, 0, 1, -1};
struct node
{
    char g[40][40];
    int id, cnt;
} mp[105];
void BlueFire()
{
    int n, m, k;
    cin >> n >> m >> k;
    k++;
    for (int i = 1; i <= k; i++)
    {
        mp[i].id = i;
        for (int j = 1; j <= n; j++)
            for (int p = 1; p <= m; p++)
                cin >> mp[i].g[j][p];

        for (int j = 2; j < n; j++)
            for (int p = 2; p < m; p++)
            {
                bool flag = 0;
                for (int q = 0; q < 4; q++)
                {
                    int tx = j + dx[q], ty = p + dy[q];
                    if (tx > n || ty > m || tx <= 0 || ty <= 0)
                    {
                        flag = 1;
                        break;
                    }
                    if (mp[i].g[tx][ty] == mp[i].g[j][p])
                    {
                        flag = 1;
                        break;
                    }
                }
                if (!flag)
                    mp[i].cnt++;
            }
    }

    sort(mp + 1, mp + 1 + k, [](node &a, node &b)
         { return a.cnt > b.cnt; });
    vector<PII> ans;
    for (int i = 2; i <= k; i++)
    {
        for (int j = 1; j <= n; j++)
            for (int p = 1; p <= m; p++)
            {
                if (mp[i].g[j][p] != mp[i - 1].g[j][p])
                    ans.push_back({j, p});
            }
        ans.push_back({-1, mp[i].id});
    }
    cout << mp[1].id << endl;
    cout << ans.size() << endl;
    for (auto c : ans)
    {
        if (c.first == -1)
            cout << 2 << " " << c.second << endl;
        else
            cout << 1 << " " << c.first << " " << c.second << endl;
    }

    return;
}
posted @ 2023-08-10 15:37  布鲁诺邦古耐夫  阅读(46)  评论(0)    收藏  举报