Codeforces Round #649 (Div. 2)

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

传送门

A. XXXXX

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

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

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 
#include 
#include 
#include 

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 
#include 
#include 
#include 
#include 

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;
}

你可能感兴趣的:(CodeForces,构造,思维)