CF Gym 100637F The Pool for Lucky Ones (思维,或者暴力)

题意:给你一串非负整数,可以将一个非零数减1,加到相邻的数字上,要使其中所有最大数字的和最小。

题解:模拟可以过。也可以分析,可以要减少最大数字和,如果最大数字出现大于等于3次,可以把最大数字加一,或者把某个最大数字减一,最大数字出现减少一次。但是要注意一些特殊情况,下面详述。

先扫一遍,如果最大数字为0,那么输出0,如果最大数字为1,那么如果可以合并成2的话,那么就输出2,否则输出数字和sum。否则,看最大数字出现次数,如果为一次,那么检查,周围是否有比它小3的数字,(如果只是比它小2的话,那么操作完以后至少会出现两个次大的数字),如果有还有检查一下操作前是否有次大的数字,然后根据检查情况输出Max或Max-1;如果出现两次,检查两个最大数字周围有没有比它小2的数字,如果有输出Max,没有的话输出Max+1,(Max>=2且不满足前者,周围一定有数字非零);对于次数大于等于3次的,检查最大数字周围有没有非零数字,如果有输出Max+1,否则sum-Max。

#include<cstdio>

#include<cmath>

#include<vector>

#include<map>

#include<set>

#include<algorithm>



using namespace std;



//#define local

typedef long long ll;

const int maxn = 1e5+5;

int p[maxn];

int main()

{

#ifdef local

    freopen("in.txt","r",stdin);

    //freopen("out.txt","w",stdout);

#endif // local

    int n;

    scanf("%d",&n);

    ll Max = 0;

    int pos = -1;

    for(int i = 0; i < n ;i++){

        scanf("%d",p+i);

        if(p[i]>Max){

            Max = p[i];pos =  i;

        }

    }

    if(Max == 0){ printf("0"); return 0;}

    if(Max == 1){

        int sum = p[0];

        bool canMerge = false;

        for(int i = 1; i < n; i++){

            sum += p[i];

            if(p[i]&&p[i-1]) { canMerge = true; break;  }

        }

        if(canMerge) printf("2");

        else printf("%d",sum);

        return 0;

    }

    long long sum = 0;

    bool canMerge = false;

    bool lessone = false;



    for(int i = pos; i < n; i++){

        if(p[i] == Max) sum += Max;

    }

    if(sum == Max){

        if(pos>0) { if(p[pos-1]<=p[pos]-3)lessone = true; }

        if(pos<n-1) { if(p[pos+1]<=p[pos]-3)lessone = true; }

        if(lessone) {

            for(int i = 0; i < n; i++){

                if(p[i] == Max-1) {

                    printf("%d",Max);

                    return 0;

                }

            }

            printf("%d",Max-1);

        }

        else printf("%d",Max);

        return 0;

    }

    if(sum == Max*2){ //keng

        for(int i = pos; i < n; i++){

            if(p[i] == Max){

                if((i>0&& p[i-1]<= Max-2 )|| (i<n-1&& p[i+1] <= Max-2 ) ){

                     printf("%d",Max); return 0;

                }

            }

        }

        printf("%d",Max+1);

    }



    for(int i = pos; i < n; i++){

        if(p[i] == Max){

            if((i>0&& p[i-1])|| (i<n-1&& p[i+1] ) )

                { printf("%d",Max+1); return 0; }

        }

    }



    printf("%I64d",sum-Max);

    return 0;

}

 

你可能感兴趣的:(for)