Codeforces Round 889 (Div. 2) (C1~C2)

这篇具有很好参考价值的文章主要介绍了Codeforces Round 889 (Div. 2) (C1~C2)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

掉大分,C1被sb错误困扰。
提示如果C1会了但不会C2,也应该先将C1解法看一遍

C1 Dual (Easy Version)

题意

给定长度为 n n n 的数组 a a a,( n < = 20 , − 20 < = a i < = 20 n<=20,-20<=a_i<=20 n<=2020<=ai<=20),每次操作可以任选 i , j i, j i,j,使得 a i = a i + a j a_i = a_i + a_j ai=ai+aj i i i 可以等于 j j j)。问最多 50 50 50 次操作以内如何将给定数组变成非降序。

思路

以下出现的 c1,c2等都代表执行操作的次数 c1代表执行一次,以此类推。
简单版本给了 50 50 50 次操作机会理应是好想的,假如现在告诉你数组数字全都是非负数或者都是负数,是否能在 19 19 19 次操作以内将其变成非降序。方法是很好想到的,如果全是正数就从前往后累加一遍,负数就从后往前累加一遍即可。

for(int i = 2; i <= n; i ++){ // 全是非负数累加一次 c19  c10 + c19 = c29
    ans.push_back({i, i - 1});
}
for(int i = n - 1; i >= 1; i --){ // 累加 c19   c12 + c19 = c31
    ans.push_back({i, i + 1});
}

那么现在问题变成如何将数组变成全部非负或全负,这个问题也很好实现,如果最小负数 + + + 最大正数 > = 0 >=0 >=0 ,那么我们将所有负数加上最大正数不就可以了吗,反之亦然。这个操作的次数同样不会超过 20 20 20 次。
19 + 19 = 38 < 50 19 + 19 = 38 < 50 19+19=38<50 解法成立。
博主写题的时候犯蠢没想到这个,写了个有点麻烦的写法,还写错了找了一小时bug,真逆天。

解法较为简单,代码就不放了,想看的可以参考一下C2的代码。

C2 Dual (Hard Version)

题意

和C1唯一的区别是,要求操作数在 31 31 31 次以内。

思路

思路继承自C1解法,使用了分类的讨论的方法,码量虽然有点大,但较为容易理解都是判断语句,并且在代码中有详细注释,直接看代码即可。文章来源地址https://www.toymoban.com/news/detail-617352.html

代码

#include <bits/stdc++.h>
using namespace std;

#define ll long long
// const int N = 2e5 + 10;

int a[100];
struct node{
    int b, id;
    bool operator < (const node &A)const{
        return b < A.b; // 按大小排序
    }
}s[100];
void solve(){
    int n;
    cin >> n;
    int sum1 = 0, sum2 = 0; // 记录负数和正数的数量
    for(int i = 1; i <= n; i ++){
        cin >> a[i];
        if(a[i] < 0) sum1 ++;
        else sum2 ++;
        s[i] = {a[i], i};
    }
    sort(s + 1, s + 1 + n);
    

    if(sum1 == 0 && sum2 == 0){ // 全0
        cout << "0\n";
        return ;
    }   

    vector<pair<int, int>> ans;
    
    // 以下出现的 c1,c2等都代表执行操作的次数 c1代表执行一次,以此类推
    if(sum2 >= sum1){ // 正数数量 >= 负数
        if(s[1].b + s[n].b >= 0){ // 最小负数 + 最大正数 >= 0 那么先将负数变成非负 <= c10 
            for(int i = 1; i <= n; i ++){
                if(a[i] < 0) ans.push_back({i, s[n].id});
            }
            for(int i = 2; i <= n; i ++){ // 全是非负数累加一次 c19  c10 + c19 = c29
                ans.push_back({i, i - 1});
            }
        }
        else { // 最小负数 + 最大正数 < 0
            if(sum2 <= 12){
                for(int i = 1; i <= n; i ++){ // 将所有正数变成负数 <= c12
                    if(a[i] > 0) ans.push_back({i, s[1].id});
                }
                for(int i = n - 1; i >= 1; i --){ // 累加 c19   c12 + c19 = c31
                    ans.push_back({i, i + 1});
                }
            }
            else{ // 正数数量 >= 13 负数数量 <= 7
                for(int i = 1; i <= 5; i ++){ // 将最大的正数翻倍c5次 就算是1 5次后也等于 32  最小负数-20 相加为正数
                    ans.push_back({s[n].id, s[n].id});
                }
                for(int i = 1; i <= n; i ++){ // 将所有负数变成正数 <= c7
                    if(a[i] < 0) ans.push_back({i, s[n].id});
                }
                for(int i = 2; i <= n; i ++){
                    ans.push_back({i, i - 1}); // 累加 c19  c5 + c7 + c19 = c31
                }
            }
        }
    }
    else{ // 一样的思路
        if(s[1].b + s[n].b <= 0){ // 最小负数 + 最大正数 <= 0 那么先将正数变非正 <= c10 
            for(int i = 1; i <= n; i ++){
                if(a[i] > 0) ans.push_back({i, s[1].id});
            }
            for(int i = n - 1; i >= 1; i --){ // 全是非正数累加一次 c19  c10 + c19 = c29
                ans.push_back({i, i + 1});
            }
        }
        else { // 最小负数 + 最大正数 > 0
            if(sum1 <= 12){
                for(int i = 1; i <= n; i ++){ // 将所有负数变成正数 <= c12
                    if(a[i] < 0) ans.push_back({i, s[n].id});
                }
                for(int i = 2; i <= n; i ++){ // 累加 c19   c12 + c19 = c31
                    ans.push_back({i, i - 1});
                }
            }
            else{ // 负数数量 >= 13 正数数量 <= 7
                for(int i = 1; i <= 5; i ++){ // 将最小的负数翻倍c5次 就算是-1 5次后也等于 -32  最大正数20 相加为负数
                    ans.push_back({s[1].id, s[1].id});
                }
                for(int i = 1; i <= n; i ++){ // 将所有正数变成负数 <= c7
                    if(a[i] > 0) ans.push_back({i, s[1].id});
                }
                for(int i = n - 1; i >= 1; i --){
                    ans.push_back({i, i + 1}); // 累加 c19  c5 + c7 + c19 = c31
                }
            }
        }
    }
    
    cout << (int)ans.size() << "\n";
    for(auto [i, j] : ans){
        cout << i << " " << j << "\n";
    }
}

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

    int t;
    cin >> t;
    while(t --){
        solve();
    }
    return 0;
}

D Earn or Unlock (待补)

到了这里,关于Codeforces Round 889 (Div. 2) (C1~C2)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Codeforces Round 867 (Div. 3)

    从所有a[i]+i-1=t的选择种取个max即可 实际上就是取同符号乘积的最大值 找规律,发现结果与边长n的关系是:res = n * (n + 3) - (n - 2) ①当n为奇数时,除了1其他均无解 ②当n为偶数时,我们可以构造一个形如n,1,n - 2,3,...的数列 首先我们可以发现n必定出现在起始位置。如果n不在起

    2024年02月02日
    浏览(35)
  • Codeforces Round 894 (Div. 3)

    签到题 a数组里,大于等于前一个值的a[i]会被写到b里。直接遍历b,如果b[i]比前一个小就在它前面插一个相等的值 计算反过来的长度,判断是否相等就行 对于没有重复口味的集合,能选出的方案是n*(n-1)/2 (从n个里面选2个的组合数)。二分找出需要多少不同口味的冰淇淋,

    2024年02月11日
    浏览(31)
  • Codeforces Round 882 (Div. 2)

    目录 A. The Man who became a God  题目分析: B. Hamon Odyssey 题目分析: C. Vampiric Powers, anyone? 题目分析:  n个人分成k组,每一组的力量都是 这样的,那么如果分成k组那么就会有k-1个力量不被统计,将力量总和减去前k-1个最大的力量就是最小的结果   将数组分组,每个组内进行按位与

    2024年02月05日
    浏览(38)
  • Codeforces Round 881 (Div. 3)

    给定一个数组,给每个元素涂色。求最大的代价。 代价为每个颜色的代价和。 每个颜色的代价为涂了该颜色的元素的极差。 因为是极差,每个元素要么对答案有正的贡献,要么有负的贡献,要么无贡献。且正负贡献的个数要相同。 因为要最大值,自然就是想有正贡献的是最

    2024年02月09日
    浏览(31)
  • Codeforces Round 926 (Div. 2)

    类似于倍投法,就是在一赔一的情况下,第一次压一块钱,每输一次就押注上一次两倍的金额. 假如资金无限的话,这种方法赢的期望为无穷大.原理类似于二进制,不论你输再多次,只要赢一次总额就增加了1.比如 15 二进制1111,前3把一直输,但是只要第4把赢,就一定可以增加 1

    2024年02月20日
    浏览(34)
  • Codeforces Round 866 (Div. 2)

    给出一个仅由_或^组成的字符串,你可以在任意位置添加_或^字符,使得字符串满足: 任意字符要么属于^_^的一部分,要么属于^^的一部分。求最少添加的字符数量。 对于_我们只需处理没有组成^_^的_: ①如果_在首位置且左边没有^则添加^ ②如果_在尾位置且右边没有^则添加

    2023年04月25日
    浏览(40)
  • Codeforces Round 871 (Div. 4)

    给定n个长度为10的字符串,问其与codeforces字符串的对应下标字母不同的个数。 对于每个字符串从前往后依次和“codeforces”对应字符比较然后统计不同字母数即可 给定长度为n的数组,问连续相邻为0的最大长度 维护一个全局最大长度res,和当前连续序列的长度cnt。从前往后扫

    2024年02月03日
    浏览(43)
  • Codeforces Round 920 (Div. 3)

    Codeforces Round 920 (Div. 3) 题意:随机给出正方形在平面坐标系上的四个顶点的坐标,求正方形的面积,正方形边与xy轴平行。 思路:因为正方形与坐标轴平行,所以找出相同的两x或y坐标即可找到一条边的长度,平方就是面积,注意结果返回整型。 AC code: 题意:给出两个01字符

    2024年01月17日
    浏览(33)
  • Codeforces Round 868 Div 2

    要求构造一个仅包含 (1) 和 (-1) 的长度为 (n) 的数组 (a) ,使得存在 (k) 个下标对 ((i, j), i j) 满足 (a_i times a_j = 1) 。 当有 (x) 个 (1) , (y) 个 (-1) 时,其满足条件的下标对数量为 (frac{x (x - 1)}{2} + frac{y (y - 1)}{2}) 。 由于 (n) 只有 (100) ,直接枚举 (x) 即可。

    2024年02月01日
    浏览(32)
  • Codeforces Round 858 (Div. 2)题解

    目录 A. Walking Master(贪心) 题面翻译 思路: 代码实现  B. Mex Master(贪心) 题面翻译: 思路: 代码实现 C. Sequence Master(数学) 题面翻译: 思路: 代码实现 YunQian is standing on an infinite plane with the Cartesian coordinate system on it. In one move, she can move to the diagonally adjacent point on the

    2023年04月08日
    浏览(71)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包