备战蓝桥杯---贪心刷题2

话不多说,直接看题:

首先我们大致分析一下,先排序一下,K==n,那就全部选。

当k<n时,k是偶数,那么结果一定非负,因为假如负数的个数有偶数个,那么我们成对选它,假如是奇数个,我们就把某一个负数选出,再成对选即可。

若k是奇数,那么所有数均负,那么答案《0,如果至少存在一个非负数,那我们先选一个非负数,然后问题就转化成了上一个形式。

因此我们排一下序,假如k是偶的,那么我们从两端成对的选,k是奇数,那么一定先选正的(若选负的那么后面也是选奇数个,这样就没有区别了),接下来就是刚才的问题了。

下面是AC代码:

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
const int N=100010,mod=1e9+9;
typedef long long LL;
int n,k;
int a[N];
int main(){
    cin>>n>>k;
    for(int i=0;i<n;i++) scanf("%d",&a[i]);
    sort(a,a+n);
    int res=1;
    int l=0,r=n-1;
    int sign=1;

    if(k%2){
        res=a[r--];
        k--;
        if(res<0) sign=-1;
    }
    while(k){
        LL x=(LL)a[l]*a[l+1],y=(LL)a[r-1]*a[r];
        if(x*sign>y*sign){
            res=x%mod*res%mod;
            l+=2;
        }
        else{
            res=y%mod*res%mod;
            r-=2;
        }
        k-=2;
    }
    cout<<res;
}

接题:

首先,后缀表达式也可以实现括号操作,首先假如没有负号,那么都是直接相加。

同时我们可以把减号从M变成1(1-(a-b-c---)),最多有N+M个减号。

因此我们减一个最小值,同时必须加最大值(第一个一定是正的),其他加绝对即可。

下面是AC代码:

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=200010;
int n,a[N],m;
int main(){
    cin>>n>>m;
    int k=n+m+1;
    for(int i=0;i<k;i++) scanf("%d",&a[i]);
    
    if(m==0){
        LL res=0;
        for(int i=0;i<k;i++) res+=a[i];
        cout<<res;
        return 0;
    }
    sort(a,a+k);
    LL res=a[k-1]-a[0];
    for(int i=1;i<k-1;i++) res+=abs(a[i]);
    cout<<res;
}

接题:

我们不妨看看前缀和,我们会惊奇的发现,我们每一次操作相当于交换一下他和它前面的前缀和,因此问题就转化成了求最大前缀和差值的min,并且两端是固定的,中间一段可以任意交换。

那么怎么求?我们不妨假设a[0]<a[n],同时确定其中的max与min。

此时,我们把图像向y轴投影压缩成一条线段,然后排一下序得到:

那么怎么走最优?

显然我们从S0开始向左两点走一步,即跨一个点走一步是最优的。

下面是AC代码:

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=300010;
LL a[N],s[N];
bool st[N];
int n;
int main(){
    int t;
    cin>>t;
    while(t--){
        scanf("%d",&n);
        s[0]=0;
        for(int i=1;i<=n;i++){
            scanf("%lld",&a[i]);
            s[i]=s[i-1]+a[i];
        }
        LL s0=s[0],sn=s[n];
        if(s0>sn) swap(s0,sn);
        sort(s,s+n+1);//注意起点在0上
        for(int i=0;i<=n;i++){
            if(s[i]==s0){
                s0=i;
                break;
            }
        }
        for(int i=0;i<=n;i++){
            if(s[i]==sn){
                sn=i;
                break;
            }
        }
        memset(st,0,sizeof(st));
        int l=0,r=n;
        for(int i=s0;i>=0;i-=2){
            a[l++]=s[i];
            st[i]=1;
        }
        for(int i=sn;i<=n;i+=2){
            a[r--]=s[i];
            st[i]=1;
        }
        for(int i=0;i<=n;i++){
            if(st[i]==0) a[l++]=s[i];
        }
        LL res=0;
        for(int i=1;i<=n;i++){
            res=max(res,abs(a[i]-a[i-1]));
        }
        cout<<res<<endl;
    }
}
相关推荐
鸽鸽程序猿12 分钟前
【算法】【动态规划】斐波那契数模型
算法·动态规划·1024程序员节
Samuel-Gyx37 分钟前
数据结构--顺序表与链表
数据结构·算法·链表·1024程序员节
小年糕是糕手38 分钟前
【数据结构】队列“0”基础知识讲解 + 实战演练
c语言·开发语言·数据结构·c++·学习·算法
无限进步_42 分钟前
【C语言】函数指针数组:从条件分支到转移表的优雅进化
c语言·开发语言·数据结构·后端·算法·visual studio
Q741_1471 小时前
C++ 分治 快速选择算法 堆排序 TopK问题 力扣 215. 数组中的第K个最大元素 题解 每日一题
c++·算法·leetcode·分治·1024程序员节·topk问题·快速选择算法
文火冰糖的硅基工坊1 小时前
[人工智能-大模型-57]:模型层技术 - 软件开发的不同层面(如底层系统、中间件、应用层等),算法的类型、设计目标和实现方式存在显著差异。
人工智能·算法·中间件
鱼儿也有烦恼1 小时前
快速学完 LeetCode top 1~50 [特殊字符]
java·算法·leetcode·1024程序员节
独自破碎E1 小时前
LeetCode 380: O(1) 时间插入、删除和获取随机元素
java·算法·leetcode
Brookty1 小时前
【算法】前缀和(二)使用
java·学习·算法·前缀和·动态规划·1024程序员节