Codeforces Round 960 (Div. 2)

Codeforces Round 960 (Div. 2)

2024.7.20 22:30————0:30

过题数2/7
补题数4/7

  • Submission Bait
  • Array Craft
  • Mad MAD Sum
  • Grid Puzzle
  • Catch the Mole(Easy Version)
  • Catch the Mole(Hard Version)
  • Polygonal Segments

A - Submission Bait

题解:
有n个数字,俩个人轮流进行操作,每次必须取出大于等于上一次的数字,无法再进行操作的失败,Alice先手,输出她能否获胜。
老规矩啊说一下错误思维,为了尽量让对手拿不到,Alice先手拿最大的,当最大数字是偶数数量时,Alice就会输,但是455,Alice先拿4的话,是可以赢的。
所以只需要存在数组a中存在一个数字,保证大于等于它的数字个数是奇数,那么Alice就可以赢
代码:

#include<bits/stdc++.h>

using namespace std;
#define int long long
int t;
priority_queue<int>b;
int a[55];

signed main() {
    cin >> t;
    while(t--) {
        int n;
        cin >> n;
        for (int i = 0; i < n; i++) {
            cin >> a[i];
            b.push(a[i]);
        }
        int res = 0;
        int lt=b.top();
        bool st = false;
        while (!b.empty()) {
            if(lt != b.top()) {
                if(res%2 == 1)st = true;
            }
            lt = b.top();
            b.pop();
            res++;
        }
        if(res % 2 == 1)st = true;
        if(st)cout << "YES" << endl;
        else cout << "NO" << endl;
    }
    return 0;
}

B - Array Craft

题解:
给出t组数据,每组包含n,x,y,要求输出n个数字,第x个数字是它前缀和的最大位置,第y个数字是它后缀的最大位置。
分俩种情况考虑,前后部分都是-1和1交替,当x<y时,非常简单,中间都是-1。当x>y时,中间是1,交替先是-1还是1由x和y的位置决定,输出数组。
代码:

#include<bits/stdc++.h>

using namespace std;
#define int long long
int t;
int a[100005];

signed main() {
    cin >> t;
    while(t--) {
        int n,x,y;
        cin >> n >> x >> y;
        if(x < y) {
            for (int i = x-1; i >= 1; i=i-2) {
                a[i] = 1;
                a[i-1] = -1;
            }
            a[x] = 1;
            a[x+1] = -1;
            for (int i = x+2; i <= y-2; i++) {
                a[i] = -1;
            }
            for (int i = y+1; i <= n; i = i+2) {
                a[i] = 1;
                a[i+1] = -1;
            }
            a[y] = 1;
            a[y-1] = -1;
        }
        else {
            for (int i = x+1; i <= n; i=i+2) {
                a[i] = -1;
                a[i+1] = 1;
            }
            for (int i = y-1; i >= 1; i = i-2) {
                a[i] = -1;
                a[i-1] = 1;
            }
            for (int i = y+1; i <= x-1; i++) {
                a[i] = 1;
            }
            a[x] = 1;
            a[x+1] = -1;
            a[y] = 1;
            a[y-1] = -1;
        }
        for (int i = 1; i <= n; i++) {
            cout << a[i] << ' ';
        }
        cout << endl;
    }
    return 0;
}

C - Mad MAD Sum

题解:
题意比较复杂,每次进行俩个操作,第一个操作是将a数组的值全部加起来,第二个操作是从第一位开始对于到当前位置的区间数组进行MAD运算再赋值给a数组,MAD运算就是至少包含俩个的数字中的最大数字。
直接对其进行先进行一次操作,得到的数组在非0以后的第一个数字可能是奇数,后面的数字都至少是偶数,最后一个数字依次右移,所以再进行一次操作,就可以确保之后每次的数组都相当于直接右移一位,相加即可。
代码:

#include<iostream>
#include<queue>
#include<algorithm>
#include<cmath>
#include<utility>
#include<map>

using namespace std;
#define int long long
const int N = 2e5+10;
int t,n;
int a[N];

signed main() {
    cin >> t;
    while(t--) {
        cin >> n;
        int b[N],c[N];
        map<int,int>mp;
        int sum = 0;
        for (int i = 1; i <= n; i++) {
            cin >> a[i];
            sum+=a[i];
            mp[a[i]]++;
            b[i] = b[i-1];
            if(mp[a[i]] == 2) b[i] = max(a[i],b[i-1]);
        }
        mp.clear();
        for (int i = 1; i <= n; i++) {
            sum+=b[i];
            mp[b[i]]++;
            c[i] = c[i-1];
            if(mp[b[i]] == 2) c[i] = max(b[i],c[i-1]);
        }
        for (int i = 1; i <= n; i++) {
            if(c[i] != 0) {
                sum += (n-i+1)*c[i];
            }
        }
        cout << sum << endl;
    }
    return 0;
}

D - Grid Puzzle

题解:
给定数字n代表一个n行n列的地图,给出n个数字,要求将每一行的前a[n]个涂成白色,有俩种涂色方式,涂一整行或者涂一个2*2的大方块,
可以看出当这行的黑块超过4个时,整行涂色比方块涂色更有优势,当不到4个时,dp找出最小值。
代码:

#include<iostream>
#include<queue>
#include<algorithm>
#include<cmath>
#include<utility>
#include<map>
#include<vector>

using namespace std;
const int N = 2e5+10;
int dp[N][5];
int n,t;
int a[N];

signed main() {
    cin >> t;
    while(t--){
        cin >> n;
        for (int i = 1; i <= n; i++) {
            cin >> a[i];
        }
        dp[0][0] =  0;
        for (int i = 0; i <= n; i++) {
            for (int j = 0; j <= 3; j++) {
                dp[i][j] = 2e9+10;
            }
        }
        dp[0][0] =  0;
        for (int i = 1; i <= n; i++) {
            int ls = 1e10+5;
            for (int j = 0; j <= 3; j++) {
                ls = min(ls,dp[i-1][j]);
            }
            dp[i][0] = ls+1;
            if(a[i] >= 5) {
                dp[i][0] = dp[i-1][0]+1;
            }
            else if(a[i] > 2){
                dp[i][0] = min(dp[i][0],dp[i-1][3]);
                dp[i][1] = min(dp[i][1],dp[i-1][2]+1);
                dp[i][2] = min(dp[i][2],dp[i-1][1]+1);
                dp[i][3] = min(dp[i][3],dp[i-1][0]+2);
            }
            else if(a[i] > 0){
                dp[i][0] = min(dp[i][0],dp[i-1][1]);
                dp[i][1] = min(dp[i][1],dp[i-1][0]+1);
            }
            else {
                dp[i][0] = min(dp[i-1][0],dp[i-1][1]);
                dp[i][0] = min(dp[i][0],dp[i-1][2]);
                dp[i][0] = min(dp[i][0],dp[i-1][3]);
            }
//            cout << dp[i][0] << ' ' << dp[i][1] << ' ' << dp[i][2] << ' ' << dp[i][3] << endl;
        }

        int mi = 2e10+10;
        for (int i = 0; i <= 3; i++) {
            mi = min(mi,dp[n][i]);
        }
        cout << mi << endl;
    }
    return 0;
}

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值