贪心专题1

 货仓选址

题目描述:

在一条数轴上有 N 家商店,它们的坐标分别为 A1~AN。现在需要在数轴上建立一家货仓,每天清晨,从货仓到每家商店都要运送一车商品。为了提高效率,求把货仓建在何处,可以使得货仓到每家商店的距离之和最小。

输入格式

第一行输入整数N。第二行N个整数A1~AN。

输出格式

输出一个整数,表示距离之和的最小值。

数据范围

1≤N≤100000

输入样例:

4
6 2 9 1
输出样例:

12

 

#include<iostream>
#include<algorithm>
using namespace std;
const int N=1e5+10;
int a[N];
int main(){
    int n;
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
    }
    sort(a+1,a+n+1);
    int sum=0;
    for(int i=1;i<=n/2;i++){
         sum+=a[n-i+1]-a[i];
    }
    cout<<sum<<endl;
}

  股票买卖 II

股票买卖 II
题意
给定一个长度为 N 的数组,数组中的第 i 个数字表示一个给定股票在第 i 天的价格。

设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。

注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

输入格式
第一行包含整数 N,表示数组长度。

第二行包含 N 个不大于 10000 的正整数,表示完整的数组。

输出格式
输出一个整数,表示最大利润。

数据范围
1≤N≤105
输入样例1:
6
7 1 5 3 6 4
输出样例1:
7
输入样例2:
5
1 2 3 4 5
输出样例2:
4
输入样例3:
5
7 6 4 3 1
输出样例3:
0
样例解释
样例1:在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6-3 = 3 。共得利润 4+3 = 7。

样例2:在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。注意你不能在第 1 天和第 2 天接连购买股票,之后再将它们卖出。因为这样属于同时参与了多笔交易,你必须在再次购买前出售掉之前的股票。

样例3:在这种情况下, 不进行任何交易, 所以最大利润为 0。
 

#include<iostream> 
using namespace std;
const int N=1e5+10;
int a[N];
int main(){
    int n,ans=0;
    cin>>n;
    for(int i=0;i<n;i++){
        cin>>a[i];
    }
    for(int i=1;i<n;i++){
        if(a[i]>a[i-1]){
            ans+=a[i]-a[i-1];
        }
    }
    cout<<ans;
    return 0;
}

糖果传递 

有 n 个小朋友坐成一圈,每人有 a[i] 个糖果。
每人只能给左右两人传递糖果。
每人每次传递一个糖果代价为 1。
求使所有人获得均等糖果的最小代价。

输入格式
第一行输入一个正整数 n,表示小朋友的个数。

接下来 n 行,每行一个整数 a[i],表示第 i 个小朋友初始得到的糖果的颗数。

输出格式
输出一个整数,表示最小代价。

数据范围
1≤n≤1000000,
0≤a[i]≤2×109,
数据保证一定有解。

输入样例:
4
1
2
5
4
输出样例:
4

我们设 xi为第i个人分给第i-1个人的糖果数,可正可负,用方程表示后

 我们求解的答案|x1|+|x2|+|x3|+..... +|xn|的最小值

#include<iostream>
#include<algorithm>
using namespace std;
const int N=1e6+10;
typedef long long LL;
long long  a[N],c[N];
int main(){
    int n;
    cin>>n;
    LL sum=0;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        sum+=a[i];
    }
    sum=sum/n;
    c[n]=sum-a[n];
    for(int i=n-1;i>=2;i--){
        c[i]=c[i+1]+sum-a[i];
    }
    c[1]=0;
    sort(c+1,c+n+1);
    LL ans=0;
    for(int i=1;i<=n/2;i++){
    ans+=(LL)(c[n-i+1]-c[i]);
    }
cout<<ans;
return 0;
}

 112. 雷达设备

1.题目
假设海岸是一条无限长的直线,陆地位于海岸的一侧,海洋位于另外一侧。

每个小岛都位于海洋一侧的某个点上。

雷达装置均位于海岸线上,且雷达的监测范围为 d,当小岛与某雷达的距离不超过 d时,该小岛可以被雷达覆盖。

我们使用笛卡尔坐标系,定义海岸线为 x 轴,海的一侧在 x轴上方,陆地一侧在 x 轴下方。

现在给出每个小岛的具体坐标以及雷达的检测范围,请你求出能够使所有小岛都被雷达覆盖所需的最小雷达数目。

输入格式
第一行输入两个整数 n和 d,分别代表小岛数目和雷达检测范围。

接下来 n 行,每行输入两个整数,分别代表小岛的 x,y轴坐标。

同一行数据之间用空格隔开。

输出格式
输出一个整数,代表所需的最小雷达数目,若没有解决方案则所需数目输出 −1。

数据范围
1 ≤ n ≤ 1000 1≤n≤10001≤n≤1000,
− 1000 ≤ x , y ≤ 1000 −1000≤x,y≤1000−1000≤x,y≤1000

输入样例:

3 2
1 2
-3 1
2 1

输出样例:

2

#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=1010;
struct segment{
    double l,r;
    bool operator<(const segment& t ){
        return r<t.r;
    }
}seg[N];
int main(){
    int n,d;
    cin>>n>>d;
    bool failed=false;
    for(int i=0;i<n;i++){
        int  x,y;
        float dx;
        cin>>x>>y;
        if(y>d){
            failed=true;
        }
        else{
        dx=sqrt(pow(d,2)-pow(y,2));
        seg[i].l=x-dx;
        seg[i].r=x+dx;}
    }
    if(failed==true){
        puts("-1");
    }
    else{
    sort(seg,seg+n);
    int ans=0;
    float last=-1e20;
    for(int i=0;i<n;i++){
        if(seg[i].l>last){
            ans++;
            last=seg[i].r;
        }
        
    }
        cout<<ans<<endl;
    }
}

几个人一起出去吃饭是常有的事。但在结帐的时候,常常会出现一些争执。
现在有 n 个人出去吃饭,他们总共消费了 S 元。
其中第 i 个人带了ai 元。
幸运的是,所有人带的钱的总数是足够付账的,但现在问题来了:每个人分别要出多少钱呢?

为了公平起见,我们希望在总付钱量恰好为 S 的前提下,最后每个人付的钱的标准差最小。
这里我们约定,每个人支付的钱数可以是任意非负实数,即可以不是1分钱的整数倍。你需要输出最小的标准差是多少。

#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=500010;
int  a[N];
int main(){
    int n;
    long double s;
    scanf("%d %llf",&n,&s);
    for(int i=0;i<n;i++){
        cin>>a[i];
    }
    sort(a,a+n);
     long double ave=s/n;
    long double res=0;
    for(int i=0;i<n;i++){
        double cur=s/(n-i);
        if(a[i]<cur)cur=a[i];
        res+=(cur-ave)*(cur-ave);
        s-=cur;
    }
   printf("%.4llf",sqrt(res/n));
}

 1239. 乘积最大

给定 N 个整数 A1,A2,…AN。

请你从中选出 K 个数,使其乘积最大。

请你求出最大的乘积,由于乘积可能超出整型范围,你只需输出乘积除以 1000000009 的余数。

注意,如果 X<0, 我们定义 X 除以 1000000009 的余数是负(−X)除以 1000000009 的余数,即:0−((0−x)%1000000009)

分情况讨论

当k=n;全部取

k<n;k为偶数时,取绝对值最大的偶个负数与偶个整数;负数选择时成对地选

k为奇数时,特殊情况如果全是负数,选择最大的k个负数

至少存在一个非负数,那么选择这个最大的数,然后从n-1个数选择 k-1(偶数)个数,转化为情况一    

#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;

const int  N=1e5+10,mod=1000000009;
int a[N];
int main(){
    int n,k;
    scanf("%d %d",&n,&k);
    for(int i=0;i<n;i++){
        scanf("%d",&a[i]);
    }
    sort(a,a+n);
    int l=0,r=n-1;
    int  sign=1;
    LL res=1;
    if(k%2){
        res=a[r--];
        k--;
        if(res<0){
            sign=-1;
        }
    }
    while(k){
        LL x=(LL)a[l]*a[l+1];
        LL y=(LL)a[r]*a[r-1];
        if(x*sign>y*sign){
            res=x%mod*res%mod;
            l+=2;
        }
        else{
            res=y%mod*res%mod;
            r-=2;
        }
         k=k-2;
    }
    printf("%d",res);
}

题目描述
给定N 个加号、M 个减号以及N + M + 1 个整数A1,A2,…,AN+M+1
小明想知道在所有由这N 个加号、M 个减号以及N + M +1 个整数凑出的合法的后缀表达式中,结果最大的是哪一个?
请你输出这个最大的结果。
例如使用1 2 3 + -,则“2 3 + 1 -” 这个后缀表达式结果是4,是最大的。
输入
第一行包含两个整数N 和M。
第二行包含N + M + 1 个整数A1,A2,…,AN+M+1
0<=N,M<=100000,-109<=Ai<=109
输出
输出一个整数,代表答案。
样例输入

1 1
1 2 3
1
2
样例输出

4

#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N=2e5+10;
int a[N];
int main(){
    int n,m;
LL sum=0;
    scanf("%d %d",&n,&m);
         int k=m+n+1;
         for(int i=0;i<k;i++){
        scanf("%d",&a[i]);
    }
    if(!m){
        for(int i=0;i<k;i++)
        sum+=a[i];

    }
    else{
   
    
    sort(a,a+k);
    
   sum=a[k-1]-a[0];
   for(int i=1;i<=k-2;i++){
       sum+=abs(a[i]);
   }}
    cout<<sum;
}

 灵能传输

问题描述
你控制着 n 名高阶圣堂武士,方便起见标为 1,2,··· ,n。每名高阶圣堂武士
需要一定的灵能来战斗,每个人有一个灵能值 a i 表示其拥有的灵能的多少(a i
非负表示这名高阶圣堂武士比在最佳状态下多余了 a i 点灵能,a i 为负则表示这
名高阶圣堂武士还需要 −a i 点灵能才能到达最佳战斗状态) 。现在系统赋予了
你的高阶圣堂武士一个能力,传递灵能,每次你可以选择一个 i ∈ [2,n − 1],若
a i ≥ 0 则其两旁的高阶圣堂武士,也就是 i − 1、i + 1 这两名高阶圣堂武士会从
i 这名高阶圣堂武士这里各抽取 a i 点灵能;若 a i < 0 则其两旁的高阶圣堂武士,
也就是 i−1,i+1 这两名高阶圣堂武士会给 i 这名高阶圣堂武士 −a i 点灵能。形
式化来讲就是 a i−1 + = a i ,a i+1 + = a i ,a i − = 2a i 。
灵能是非常高效的作战工具,同时也非常危险且不稳定,一位高阶圣堂
武士拥有的灵能过多或者过少都不好,定义一组高阶圣堂武士的不稳定度为
max n
i=1 |a i |,请你通过不限次数的传递灵能操作使得你控制的这一组高阶圣堂武
士的不稳定度最小。

输入描述
本题包含多组询问。
输入的第一行包含一个正整数 TTT 表示询问组数。 接下来依次输入每一组询问。
每组询问的第一行包含一个正整数 nnn,表示高阶圣堂武士的数量。
接下来一行包含 nnn 个数 a1,a2,⋅⋅⋅,ana_1,a_2,··· ,a_na1​,a2​,⋅⋅⋅,an​。
其中,T≤3,3≤n≤300000,∣ai∣≤109T \leq 3,3 \leq n \leq 300000,|ai| \leq 10^9T≤3,3≤n≤300000,∣ai∣≤109.
输出描述
输出 TTT 行。每行一个整数依次表示每组询问的答案。
输入输出样例
示例
输入
3
3
5 -2 3
4
0 0 0 0
3
1 2 3
输出
3
0
3
运行限制
最大运行时间:1s
最大运行内存: 256M

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值