【C++】「一本通 1.1 练习 1」数列极差

【来源】

一本通题库-1427
LibreOJ-10005
vjudge

注意:一本通题库和LibreOJ题意相同,但输入格式不同。代码以一本通题库为准。

【题目描述】

在黑板上写了 N N 个正整数作成的一个数列,进行如下操作:每一次擦去其中的两个数 a a b b ,然后在数列中加入一个数 a × b + 1 a×b+1 ,如此下去直至黑板上剩下一个数,在所有按这种操作方式最后得到的数中,最大的 m a x max ,最小的为 m i n min ,则该数列的极差定义为 M = m a x m i n M=max−min

【输入格式】

第一行,一个数为 N N ;

第二行, N N 个数。

【输出格式】

输出极差。

【输入样例】

3
1 2 3

【输出样例】

2

【数据范围】

对于全部数据, 0 n 50000 0\le n\le 50000 ,保证所有数据计算均在 32 32 位有符号整数范围内。

【解析1】

贪心。

求max:每次选取两个最小的数。
求min:每次选取两个最大的数。

【代码1】

#pragma GCC optimize(3,"Ofast","inline")
#pragma G++ optimize(3,"Ofast","inline")

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>

#define RI                 register int
#define re(i,a,b)          for(RI i=a; i<=b; i++)
#define ms(i,a)            memset(a,i,sizeof(a))
#define MAX(a,b)           (((a)>(b)) ? (a):(b))
#define MIN(a,b)           (((a)<(b)) ? (a):(b))

using namespace std;
 
typedef long long LL;

int const N=5e4+5;

int n;
int a[N],b[N];

int cmp(int a,int b) {
    return a>b;
}

int main() {
    scanf("%d",&n);
    for(int i=1; i<=n; i++) scanf("%d",&a[i]);
    for(int i=1; i<=n; i++) b[i]=a[i];
    sort(a+1,a+n+1,cmp);
    for(int i=2; i<=n; i++) a[i]=a[i]*a[i-1]+1;
    int amin=a[n];
    sort(b+1,b+n+1);
    for(int i=2; i<=n; i++) {
        b[i]=b[i]*b[i-1]+1;
        sort(b+1,b+n+1);
    }
    int amax=b[n];
    int ans=amax-amin;
    printf("%d\n",ans);
    return 0;
}

【解析2】

贪心。

我们可以巧妙利用C++ STL里面的greater和less,以及priority_queue。
对于greater()、less()两个函数:
建堆的时候,默认是大根堆,第三个参数用greater()会变成小根堆。less()反之。
排序的时候,默认是从小到大,但是第三个参数用greater()会变成从大到小。less()反之。

用优先队列代替数组。

两种方法的时间复杂度是相似的。

【代码2】

#pragma GCC optimize(3,"Ofast","inline")
#pragma G++ optimize(3,"Ofast","inline")

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <queue>
#include <functional>

#define RI                 register int
#define re(i,a,b)          for(RI i=a; i<=b; i++)
#define ms(i,a)            memset(a,i,sizeof(a))
#define MAX(a,b)           (((a)>(b)) ? (a):(b))
#define MIN(a,b)           (((a)<(b)) ? (a):(b))

using namespace std;
 
typedef long long LL;

int n;

priority_queue<int,vector<int>,greater<int> > q1;
priority_queue<int,vector<int>,less<int> > q2;

int main() {
    scanf("%d",&n);
    for(int i=1; i<=n; i++) {
        int a;
        scanf("%d",&a);
        q1.push(a);
        q2.push(a);
    }
    int amax=0;
    while(!q1.empty()) {
        if(q1.size()==1) {
            amax=q1.top();
            break;
        }
        int x=q1.top(); q1.pop();
        int y=q1.top(); q1.pop();
        q1.push(x*y+1);
    }
    int amin=0;
    while(!q2.empty()) {
        if(q2.size()==1) {
            amin=q2.top();
            break;
        }
        int x=q2.top(); q2.pop();
        int y=q2.top(); q2.pop();
        q2.push(x*y+1);
    }
    int ans=amax-amin;
    printf("%d\n",ans);
    return 0;
}

发布了106 篇原创文章 · 获赞 156 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/Ljnoit/article/details/105402490