Codeforces Round #649 (Div. 2)

本文解析了两道算法竞赛题目,包括如何快速找到数组中不符合特定条件的元素的最短连续子序列,以及如何通过识别序列中的转折点来简化问题,提供了清晰的解题思路和代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

手速思路还是太慢了,放假后要抓紧练习才行

传送门

A. XXXXX

主要思路: 首先求出全部的和是否是x的倍数,如果不是,则输出n, 如果是,那么找前后第一个余数不为0的点即可。

解题思路:
  • 首先我们对所有数求和,如果不是x的倍数,那么直接输出n
  • 然后我们判断是x的倍数的情况,那么我们只要前后找一个位置,这个位置他不是x的倍数即可,然后我们求这个长度的最大值。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

typedef long long ll;

const int N = 100010, M = 200010;

int a[N];

int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        int n, m;
        scanf("%d%d",&n,&m);
        for (int i = 1; i <= n; i++){
            scanf("%d",&a[i]);
            
        }
        int res = 0;
        int x = n + 1, y = 0;
        for (int i = 1; i <= n; i++){
            if (a[i] % m != 0){
                if (x == n + 1) x = i;
                if (y < i) y = i; 
            }
            res += a[i];
        }
        if (res % m != 0) printf("%d\n",n);
        else{
            if (x != n + 1 && y != 0){
                printf("%d\n",n - min(x,n - y + 1));
            }
            else{
                puts("-1");
            }

        }

    }
    return 0;
}


B. Most socially-distanced subsequence

主要思路:找差值最大的最小数目,找转折点存储即可。

解题思路:
  • 首先我们说明一下为什么找转折点,比如 1 3 5 6 ,他的每个的差值是 2 2 1,而且1 和 6的差值就是5,所以中间过程全部可以忽略掉,因此我们找转折点即可
  • 除了转折点,我们还需要加上首尾的位置,因为无论如何,首尾的位置都会增加当前消费的总和(每个数值都不一样)
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

typedef long long ll;

const int N = 100010, M = 200010;

int a[N];

int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        int n, m;
        scanf("%d%d",&n,&m);
        for (int i = 1; i <= n; i++){
            scanf("%d",&a[i]);
            
        }
        int res = 0;
        int x = n + 1, y = 0;
        for (int i = 1; i <= n; i++){
            if (a[i] % m != 0){
                if (x == n + 1) x = i;
                if (y < i) y = i; 
            }
            res += a[i];
        }
        if (res % m != 0) printf("%d\n",n);
        else{
            if (x != n + 1 && y != 0){
                printf("%d\n",n - min(x,n - y + 1));
            }
            else{
                puts("-1");
            }

        }

    }
    return 0;
}


C. Ehab and Prefix MEXs

主要思路:存储好没有被赋值的位置,然后当当前的值 > 我们最小赋值的值时,我们进行赋值,其他的随便赋值(1e5 + i)

解题思路:
  • 首先我们将每个位置的值都赋为 -1
  • 然后我们开一个stack,存储位置。
  • 然后我们向stack中存入位置(没有被赋值的位置)
  • 当当前值 a[i] > 我们的当前赋值的最小值时,我们进行赋值,然后stack中清除相应位置元素(里面哪一个都可以)
  • 最终我们将没有赋值的位置都赋值成 1e5 + i即可,因为不要相同,而且不要超过1e6
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <stack>

using namespace std;

typedef long long ll;

const int N = 100010, M = 200010;

int a[N], res[N];

stack<int> s;

int main(){
    int n;
    scanf("%d",&n);
    for (int i = 1; i <= n; i++){
    	scanf("%d",&a[i]);
    	res[i] = -1;
    }
    int x = 0;
    for (int i = 1; i <= n; i++){
    	s.push(i);
    	for (int j = x ; j <= a[i] - 1; j ++){
    		int t = s.top();
    		res[t] = j;
    		s.pop();
    	}
    	x = a[i];
    }
    for (int i = 1; i <= n; i++){
    	if (res[i] == -1){
    		printf("%d ",100000 + i);
    	}
    	else{
    		printf("%d ",res[i]);
    	}
    }
    puts("");
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值