首页 > 其他分享 >Codeforces #821 Div2(A~D2)题解

Codeforces #821 Div2(A~D2)题解

时间:2022-09-20 15:59:04浏览次数:115  
标签:cout min int 题解 ll D2 cin 操作 821

CF#821 Div2

A Consecutive Sum

题目:

​ 选择\(i\)和\(j\),如果\(j = i+xk(x=R)\),可以交换\(i,j\)。任意选择一段长度为k的相加。

思路:

​ 题目等价于在下标\(mod\) k 相同的数中选一个最大的。简单模拟。可以用vis标记或者优先队列。

实现:

​ 不值一提。

void solve()
{
    cin >> n >> k;
    priority_queue<int> q[105];

    for(int i = 0; i < n; i ++)
    {
        int x; cin >> x;
        q[(i + 1) % k].push(x);
    }
    ll res = 0;
    for(int i = 0; i < k; i ++)
        res += q[i].top();
    cout << res << '\n';
}

B Rule of League(分类讨论)

题目:

​ 有n个人,他们之间会进行n-1场比赛。将人分成两部分,一部分人赢了\(x\)把,另一部分人赢了\(y\)把。请问是否存在这样的情况,如果有,请输出每一局的胜者。否则输出-1。

思路:

​ 可以想到,\(x\)和\(y\)必须有一个是0,且不能都为0。因为如果一个人要赢,一定有一个人会直接输掉(也就是这个直接输的人赢0把)。

实现:

​ 判断合法的情况很简单。不过想要输出每一局的胜者需要稍作思考。

void solve()
{
    cin >> n >> x >> y;
    if(min(x, y) > 0 || max(x, y) == 0) {cout << "-1\n"; return;}
    if(x == 0)  swap(x, y);
    if((n - 1) % x != 0)    {cout << "-1\n"; return;}
    for(int i = 1; i <= (n - 1) / x; i ++)
        for(int j = 1; j <= x; j ++)
            cout << 2 + (i - 1) * x << ' ';
    cout << '\n';
}

C Parity Shuffle Sorting(构造)

题目:

​ 给出一个长度为n的序列。请你在n次操作内将其变为单调不降序列。

​ 操作:选择\(l\)和\(r\),如果\(a_l+a_r\)是偶数,那么\(a_l=a_r\),反之,\(a_r=a_l\)。

思路:

​ 对于这类限制操作次数且不要求最少操作次数的问题。我们尽量将思路靠向用完n次操作正好解决问题。每次操作,可以改变一个数,那么我们就能想到把整个序列变成一个数。

​ 我们先把头和尾变成同一个数,不管原来的是哪个都行。然后对于中间的数,根据其加和的奇偶性选择左端点或右端点。

实现:

​ 没什么值得注意的,根据思路模拟即可。

void solve()
{
    cin >> n;
    vector<int> a(n + 1);
    for(int i = 1; i <= n; i ++)
        cin >> a[i];

    if(is_sorted(all(a)))   {cout << "0\n"; return;}

    cout << n - 1 << "\n";
    cout << 1 << ' ' << n << '\n';
    int g = ((a[1] + a[n]) & 1 ? a[1] : a[n]);
    for(int i = 2; i <= n - 1; i ++)
    {
        if((g + a[i]) & 1)
            cout << 1 << ' ' << i << '\n';
        else
            cout << i << ' ' << n << '\n';
    }
}

D Zero-One(D1贪心,D2记忆化搜索)

题目:

​ 给出\(n,x,y\)和两个长度为n的01串。你可以任选两个\(l,r(l<r)\),可以取反\(a_l,a_r\)。在不同的情况下,操作的花费是不同的。1. 当\(l+1=r\)的时候,花费为x。 2.其余情况,花费为y。请问将a变成b的最小花费是多少。

思路:

​ 首先我们要想到x和y的操作是可以互换的。比如说,两次y操作可以等价一次x操作。\(a_r-a_l\)次x操作可以等价一次y操作。同时设需要改变的位置有m个。

​ D1的问题是当\(x>=y\)的时候,求解问题。由于我们知道\(x>=y\),通过贪心的策略我们可以想到我们要尽量地选择操作y。通过手推样例可以发现,除了存在有两个位置不同且这是两个相邻的位置的时候,我们的花费是\(min(x, 2 * y)\),其他的情况下花费都是m / 2 * y。

​ D2的问题是解除对\(x,y\)间关系的限制。当\(x>=y\)的情况的时候,我们已经在D1求解过了。那么接下来,我们只需要解决\(x<y\)的情况就可以了。发现\(n\)是5000,可以用\(n^2\)的DP算法求解。设状态为\(f[i][j]\),表示在需要改变的位置的序列中,\([l,r]\)的问题还没有解决时,当前的最小花费。直接递推的话,状态不是很好转移,于是选择记忆化搜索来实现这个DP。

实现:

​ 谨防爆int以及初始化。

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;

const int N = 5005;
char s1[N], s2[N];
int n;
ll x, y;
ll f[N][N];
vector<int> a;

void init()
{   
    for(int i = 0; i <= n; i ++)
        for(int j = 0; j <= n; j ++)
            f[i][j] = 2e18;
}

ll dfs(int l, int r)
{
    if(l > r)   return 0;
    if(f[l][r] != 2e18)    return f[l][r];
    ll &v = f[l][r];
    if(a[l] + 1 == a[r])
        v = min(v, dfs(l + 1, r - 1) + x);
    else
        v = min(v, dfs(l + 1, r - 1) + y);
    v = min(v, dfs(l, r - 2) + min(y, 1ll * (a[r] - a[r - 1]) * x));
    v = min(v, dfs(l + 2, r) + min(y, 1ll * (a[l + 1] - a[l]) * x));
    return v;
}

void solve()
{
    a.clear();
    cin >> n >> x >> y;
    cin >> s1 >> s2;
    
    for(int i = 0; i < n; i ++)
    {
        if(s1[i] != s2[i])
            a.push_back(i);
    }

    int m = (int)a.size();
    if(m == 0)  {cout << "0\n"; return;}
    if(m & 1)   {cout << "-1\n"; return;}

    if(x >= y) //贪心,我们可以全部选择y,除了只有两个相邻位置需要改变的情况。
    {
        if(m == 2 && a[0] + 1 == a[1])
            cout << min(x, 2 * y) << '\n';
        else
            cout << m / 2 * y << '\n';
    }
    else //DP
    {
        init();
        cout << dfs(0, m - 1) << '\n';
    }
}

int main()
{
    ios::sync_with_stdio(false);cin.tie(0);
    int _;
    cin >> _;
    while(_--)
        solve();
}

标签:cout,min,int,题解,ll,D2,cin,操作,821
From: https://www.cnblogs.com/DM11/p/16711285.html

相关文章

  • CGR1 简要题解
    G.Tree-Tac-Toe瞎扯:首先一看黑就不可能赢,最多争个平。若有度数大于\(3\)的点白直接赢了。若一个点度数为\(3\),且只有不多于\(1\)端是叶子,白也赢了。所以现在树的形......
  • js精度计算问题解决,Jsutil库源码
    为什么会存在浮点数计算精度丢失问题,这个原因不再过多赘述; JS中如何解决精度计算问题,大不部分人都知道升幂再降幂的解决方案; 但是如果直接升幂也会出现精度问题,且需......
  • sb课件的题解(复习)
    sb课件的题解(复习)不理解,为什么一个新的课件我就2题没做过,没救了CF1310C这题,我们发现它不同的子段共有\(n*(n-1)/2\)个,将其按字典序排序我们需要便捷的比较,考虑维护\(......
  • 【题解】CF1733E - Conveyor
    因为每秒只放一个球,所以对于每一个\(x+y=a\)的对角线最多只有一个球且任意两个球不会相遇,所以我们只用知道第\(t-x-y\)秒放的球的移动路径即可。等价于需要求出前\(......
  • CF round 812 div2 A-D 题解
    首先第一题TravelingSalesManProblem,给出一些坐标,就是问从原点出发,然后收集所有的点,问最少需要多少次移动这个就是求收集完那曼哈顿距离,这个距离稍加观察可以发现,就是......
  • EFCore 6级联删除问题解决Database operation expected to affect 1 row(s) but actua
    异常信息:Databaseoperationexpectedtoaffect1row(s)butactuallyaffected0row(s).Datamayhavebeenmodifiedordeletedsinceentitieswereloaded.See......
  • SP2128题解
    题意共有\(t\)个\(n\timesm\)的由.、x、o组成的字符矩阵。设矩阵中连续\(k\)格为x小A加一分,连续\(k\)格为o小B加一分。正文\(\Large{时间复杂度:}\l......
  • 【Coel.解题报告】【没事找事】CSP-S2 真题解析
    昨天刚考完CSP-S1,反正没什么想做的(最近好颓废…),来复盘一下。本次比赛评价(转载):CSP-S1是由CCF自主研发的一款全新开放世界冒险游戏。游戏发生在一个被称作「基数排序......
  • 牛客题解 珂朵莉与宇宙
    链接:https://ac.nowcoder.com/acm/problem/14600来源:牛客网题解作者岛田小雅这道题很仁慈地直接告诉了我们子区间的个数,如果直接暴力遍历所有的子区间,复杂度是\(O(\f......
  • PostgreSQL常见问题解决
    psql找不到动态链接库 2022-09-19 psql:symbollookuperror:psql:undefinedsymbol:PQsetErrorContextVisibility      解决办法:  找到PG......