贪心算法专题练习1

目录

A. 「一本通 1.1 例 1」活动安排

题目描述

输入格式

输出格式

样例

输入数据 1

输出数据 1

数据范围与提示

 B. 「一本通 1.1 例 2」种树

题目描述

输入格式

输出格式

样例

输入数据 1

输出数据 1

数据范围与提示

 C. 「一本通 1.1 例 3」喷水装置

题目描述

输入格式

输出格式

样例

输入数据 1

输出数据 1

数据范围与提示

 D. 「一本通 1.1 例 4」加工生产调度

题目描述

输入格式

输出格式

样例

输入数据 1

输出数据 1

数据范围与提示

E. 「一本通 1.1 例 5」智力大冲浪 

题目描述

输入格式

输出格式

样例

输入数据 1

输出数据 1

数据范围与提示

F. 「一本通 1.1 练习 1」数列极差 

题目描述

输入格式

输出格式

样例

输入数据 1

输出数据 1

数据范围与提示

G. 「一本通 1.1 练习 2」数列分段 

题目描述

输入格式

输出格式

样例

输入数据 1

输出数据 1

数据范围与提示

H. 「一本通 1.1 练习 3」线段 

题目描述

输入格式

输出格式

样例

输入数据 1

输出数据 1

数据范围与提示

I. 「一本通 1.1 练习 4」家庭作业 

题目描述

输入格式

输出格式

样例

输入数据 1

输出数据 1

数据范围与提示

J. 「一本通 1.1 练习 5」钓鱼 

题目描述

输入格式

输出格式

样例

输入数据 1

输出数据 1

数据范围与提示


A. 「一本通 1.1 例 1」活动安排

 

题目描述

设有 n 个活动的集合E={1,2,..,n},其中每个活动都要求使用同一资源,如演讲会场等,而在同一时间内只有一个活动能使用这一资源。每个活动 i 都有一个要求使用该资源的起始时间si​ 和一个结束时间fi​,且 si​<fi​。如果选择了活动 i ,则它在时间区间[si​,fi​) 内占用资源。若区间[si​,fi​) 与区间 [sj​,fj​) 不相交,则称活动 i 与活动 j 是相容的。也就是说,当 fi​≤sj​ 或fj​≤si​ 时,活动 i 与活动 j 相容。选择出由互相兼容的活动组成的最大集合。

输入格式

第一行一个整数 n;

接下来的 n 行,每行两个整数 si​ 和 fi​。

输出格式

输出互相兼容的最大活动个数。

样例

输入数据 1

4
1 3
4 6
2 5
1 7

Copy

输出数据 1

2

Copy

数据范围与提示

1≤n≤1000

区间问题 

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int n,cnt,p;
struct app{
    int l,r;
}a[1005];
bool cmp(app x,app y){//按右端点排序
    return x.r<y.r;
}
int main(){
    cin>>n;
    for(int i=0;i<n;i++){
        cin>>a[i].l>>a[i].r;
    }
    sort(a,a+n,cmp);
    for(int i=1;i<n;i++){
        if(a[i].l>=a[p].r){//如果左边界大于等于右边界,表示相容
            cnt++;
            p=i;
        }
    }
    cout<<cnt+1;//加1是为了加上一开始的a[0]

    return 0;
}

 B. 「一本通 1.1 例 2」种树

 

题目描述

某条街被划为 �n 条路段,这 �n 条路段依次编号为 1…�1…n。每个路段最多可以种一棵树。现在居民们给出了 ℎh 组建议,每组建议包含三个整数 �,�,�b,e,t,表示居民希望在路段 �b 到 �e 之间至少要种 �t 棵树。这些建议所给路段的区间可以交叉。请问:如果要满足所有居民的建议,至少要种多少棵树。

输入格式

第一行为 �n,表示路段数。

第二行为 ℎh,表示建议数。

下面 ℎh 行描述一条建议:�,�,�b,e,t,用一个空格分隔。

输出格式

输出只有一个数,为满足所有居民的建议,所需要种树的最少数量。

样例

输入数据 1

9
4
1 4 2
4 6 2
8 9 2
3 5 2

Copy

输出数据 1

5

Copy

数据范围与提示

30%30% 的数据满足 0<�≤10000<n≤1000,0<ℎ≤5000<h≤500;

100%100% 的数据满足 0<�≤3×1040<n≤3×104,ℎ≤5000h≤5000,0<�≤�≤3×1040<b≤e≤3×104,�≤�−�+1t≤e−b+1。

 种树,类似于区间选点

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int len,n;
ll cnt;
int v[30005];
struct app{
    ll l,r,t;
}a[5005];
bool cmp(app x,app y){
    return x.r<y.r;
}
int main(){
    cin>>len;
    cin>>n;
    for(int i=0;i<n;i++){
        cin>>a[i].l>>a[i].r>>a[i].t;
    }
    sort(a,a+n,cmp);//按右端点排序先
    for(int i=0;i<n;i++){
        for(int j=a[i].l;j<=a[i].r;j++){//遍历整个区间
            if(v[j])a[i].t--;//如果已经有树了,需要种的树减1
            if(a[i].t==0)break;//等于0表示这个区间不需要再种树了
        }
        for(int k=a[i].r,j=a[i].t;j>0;k--,j--){//如果还需要种树,都放在区间末尾
            if(!v[k])v[k]=1;//如果没被标记,就放树
            else j++;//如果被标记了,那么种树的数量不能减小,加1来抵消减的
        }
    }
    for(int i=1;i<=len;i++){//遍历整个区间看有多少棵树
        if(v[i])cnt++;
    }
    cout<<cnt;
    return 0;
}

 C. 「一本通 1.1 例 3」喷水装置

 

题目描述

Source: UVa 10382

长 �L 米,宽 �W 米的草坪里装有 �n 个浇灌喷头。每个喷头都装在草坪中心线上(离两边各 �22W​ 米)。我们知道每个喷头的位置(离草坪中心线左端的距离),以及它能覆盖到的浇灌范围。

请问:如果要同时浇灌整块草坪,最少需要打开多少个喷头?

Picture1

输入格式

输入包含若干组测试数据。

第一行一个整数 �T 表示数据组数;

每组数据的第一行是整数 �n、�L 和 �W;

接下来的 �n 行,每行包含两个整数,给出一个喷头的位置和浇灌半径(上面的示意图是样例输入第一组数据所描述的情况)。

输出格式

对每组测试数据输出一个数字,表示要浇灌整块草坪所需喷头数目的最小值。如果所有喷头都打开也不能浇灌整块草坪,则输出 −1−1 。

样例

输入数据 1

3
8 20 2
5 3
4 1
1 2
7 2
10 2
13 3
16 2
19 4
3 10 1
3 5
9 3
6 1
3 10 1
5 3
1 1
9 1

Copy

输出数据 1

6
2
-1

Copy

数据范围与提示

对于 100%100% 的数据,�≤15000n≤15000

 

 数学+贪心,首先将中间的那个那条线上的通过计算来看最上面那条线,将问题简化成是否有区间可以覆盖整个草坪的长度,如果可以找出最小区间数

 

#include<bits/stdc++.h>
using namespace std;
#define ll long long
struct app{//m表示位置,w表示半径
    double l,r;
}a[15005];
bool cmp(app x,app y){//按最左边排序
    return x.l<y.l;
}
int main(){
    int t;
    cin>>t;
    while(t--){
        int n,l,w;
        cin>>n>>l>>w;
        int cnt=0;
        for(int i=0;i<n;i++){
            int x,y;
            cin>>x>>y;
            if(2*y>=w){//如果直径比宽度小直接out
                a[cnt].l=x-sqrt(y*y-(w*w/4.0));
                a[cnt++].r=x+sqrt(y*y-(w*w/4.0));
            }
        }
        sort(a,a+cnt,cmp);
        double p=0;//一开始的左端点
        double ls=0;//表示临时变量
        int ans=0;
        for(int i=0;i<cnt;i++){
            if(a[i].l<=p){//如果都比左端点小
                ls=max(ls,a[i].r);//找最大的右端点
                if(i==cnt-1){//如果到最后一个位置了,记录最大的右端点,答案数加1
                    p=max(p,ls);
                    ans++;
                }
            }
            else{
                if(ls==0){
                    ans=-1;
                    break;
                }
                ans++;
                p=ls;//将最大的右端点记录
                if(p>=l)break;//如果已经超过了直接打破循环
                ls=0;//临时变量归0
                i--;
            }
        }
        if(p<l)ans=-1;//如果没有覆盖右端点
        cout<<ans<<"\n";
    }
    return 0;
}

 D. 「一本通 1.1 例 4」加工生产调度

 

题目描述

某工厂收到了 �n 个产品的订单,这 �n 个产品分别在 A、B 两个车间加工,并且必须先在 A 车间加工后才可以到 B 车间加工。

某个产品 �i 在 A,B 两车间加工的时间分别为 ��,��Ai​,Bi​。怎样安排这 �n 个产品的加工顺序,才能使总的加工时间最短。

这里所说的加工时间是指:从开始加工第一个产品到最后所有的产品都已在 A,B 两车间加工完毕的时间。

输入格式

第一行仅—个数据 �n ,表示产品的数量;

接下来 �n 个数据是表示这 �n 个产品在 A 车间加工各自所要的时间;

最后的 �n 个数据是表示这 �n 个产品在 B 车间加工各自所要的时间。

输出格式

第一行一个数据,表示最少的加工时间;

第二行是一种最小加工时间的加工顺序。

样例

输入数据 1

5
3 5 8 7 10
6 2 1 4 9

Copy

输出数据 1

34
1 5 4 2 3

Copy

数据范围与提示

对于 100%100%的数据, 0<�<1000,1≤��,��≤3500<n<1000,1≤Ai​,Bi​≤350。

本题的 SPJ 对行尾多余空格敏感,各位输出答案时不要留行尾多余空格~

关键问题就是不知道怎么排序,看一下代码里的注释,感兴趣的可以去了解一下Johnson法则 

//递归关系:T(S, t) = min{ ai + T(S - {i}, bi) }
//Johnson法则:
//对于流水作业调度问题,必定存在一个最优调度π,
// 使得作业π(i)和π(i + 1)满足Johnson不等式
//min{bπ(i), aπ(i + 1)} >= min{bπ(i + 1), aπ(i )}。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int n;
struct app{
    int l,r,id;
}a[1005];
bool cmp(app x,app y){
    return min(x.l,y.r)<min(x.r,y.l);
}
int dp[1005][1005];
int main(){
    cin>>n;
    for(int i=0;i<n;i++){
        cin>>a[i].l;
        a[i].id=i+1;
    }
    for(int i=0;i<n;i++)cin>>a[i].r;
    sort(a,a+n,cmp);
    int cnt=a[0].l;//等于一开始工作的时间
    for(int i=1;i<n;i++){
        if(a[i-1].r>=a[i].l){//如果在b区间工作的时间比在a区间工作的时间长
            cnt+=a[i-1].r;//答案加上最长的
            a[i+1].l-=abs(a[i].l-a[i-1].r);//a区间不会等
        }
        else{
            cnt+=a[i].l;
        }
    }
    cnt+=a[n-1].r;//加上最后b区间工作的时间
    cout<<cnt<<"\n";
    for(int i=0;i<n;i++){
        cout<<a[i].id;
        if(i!=n-1)cout<<' ';
    }
    return 0;
}

E. 「一本通 1.1 例 5」智力大冲浪 

题目描述

小伟报名参加中央电视台的智力大冲浪节目。本次挑战赛吸引了众多参赛者,主持人为了表彰大家的勇气,先奖励每个参赛者 �m 元。先不要太高兴!因为这些钱还不一定都是你的?!接下来主持人宣布了比赛规则:

首先,比赛时间分为 �n 个时段,它又给出了很多小游戏,每个小游戏都必须在规定期限 ��ti​ 前完成。如果一个游戏没能在规定期限前完成,则要从奖励费 �m 元中扣去一部分钱 ��wi​,��wi​ 为自然数,不同的游戏扣去的钱是不一样的。当然,每个游戏本身都很简单,保证每个参赛者都能在一个时段内完成,而且都必须从整时段开始。主持人只是想考考每个参赛者如何安排组织自己做游戏的顺序。作为参赛者,小伟很想赢得冠军,当然更想赢取最多的钱!注意:比赛绝对不会让参赛者赔钱!

输入格式

输入共四行。

第一行为 �m,表示一开始奖励给每位参赛者的钱;

第二行为 �n,表示有 �n 个小游戏;

第三行有 �n 个数,分别表示游戏 11 到 �n 的规定完成期限;

第四行有 �n 个数,分别表示游戏 11 到 �n 不能在规定期限前完成的扣款数。

输出格式

输出仅一行,表示小伟能赢取最多的钱。

样例

输入数据 1

10000
7
4 2 4 3 1 4 6
70 60 50 40 30 20 10

Copy

输出数据 1

9950

Copy

数据范围与提示

对于 100%100% 的数据,有 �≤500,1≤��≤�n≤500,1≤ti​≤n。

 

 家庭作业的简化版,懒得写了,套了家庭作业的皮改了一点东西

首先将问题看成是初始为0,最多可以挣多少钱的问题,求出最大的ans,然后拿总钱数sum-ans表示罚的钱,再拿奖金减去罚款即可

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int m;
int n;
int sum,ans;
struct app{
    int t,q;
}a[505];
priority_queue<int,vector<int>,less<>>pq;
bool cmp(app x,app y){
    if(x.t!=y.t)return x.t>y.t;
    return x.q>y.q;
}
int main(){
    cin>>m;
    cin>>n;
    int ppx=0;
    for(int i=0;i<n;i++){
        cin>>a[i].t;
        ppx=max(ppx,a[i].t);
    }
    for(int i=0;i<n;i++){
        cin>>a[i].q;
        sum+=a[i].q;
    }
    sort(a,a+n,cmp);
    int p=0;
    for(int i=ppx;i>=1;i--){
        while(i==a[p].t&&p<n){
            pq.push(a[p].q);
            p++;
        }
        if(pq.size()){
            ans+=pq.top();
            pq.pop();
        }
    }
    cout<<m-(sum-ans);
    return 0;
}

F. 「一本通 1.1 练习 1」数列极差 

题目描述

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

由于佳佳忙于准备期末考试,现请你帮助他,对于给定的数列,计算出相应的极差 �M。

输入格式

第一行为一个正整数 �n 表示正整数序列的长度;
在接下来的 �n 行中,每行输入一个正整数。
接下来的一行有一个 00,表示数据结束。

输出格式

输出只有一行,为相应的极差 �d。

样例

输入数据 1

3
1
2
3
0

Copy

输出数据 1

2

Copy

数据范围与提示

对于全部数据,0≤�≤500000≤n≤50000,保证所有数据计算均在 3232 位有符号整数范围内。

 

 这个就不需要太多思维了,直接暴力就行

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int n;
priority_queue<ll,vector<ll>,greater<>>pq;
priority_queue<ll,vector<ll>,less<>>pq1;
int main(){
    cin>>n;
    for(int i=0;i<n;i++){
        ll x;
        cin>>x;
        pq.push(x);
        pq1.push(x);
    }
    while(pq.size()>1){//每次算最小的两个数
        ll x=pq.top();
        pq.pop();
        ll y=pq.top();
        pq.pop();
        pq.push(x*y+1);
    }
    while(pq1.size()>1){//每次算最大的两个数
        ll x=pq1.top();
        pq1.pop();
        ll y=pq1.top();
        pq1.pop();
        pq1.push(x*y+1);
    }
    cout<<abs(pq.top()-pq1.top());
    return 0;
}

G. 「一本通 1.1 练习 2」数列分段 

题目描述

对于给定的一个长度为 �N 的正整数数列 ��Ai​,现要将其分成连续的若干段,并且每段和不超过 �M(可以等于 �M),问最少能将其分成多少段使得满足要求。

输入格式

第一行包含两个正整数 �,�N,M,表示了数列 ��Ai​ 的长度与每段和的最大值;

第二行包含 �N 个空格隔开的非负整数 ��Ai​。

输出格式

输出文件仅包含一个正整数,输出最少划分的段数。

样例

输入数据 1

5 6
4 2 4 5 1

Copy

输出数据 1

3

Copy

数据范围与提示

对于 20%20% 的数据,有�≤10N≤10;

对于 40%40% 的数据,有�≤1000N≤1000;

对于 100%100% 的数据,有 �≤105,�≤109N≤105,M≤109,�M 大于所有数的最大值。

 

按照题意模拟就行 

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int n,m,cnt=1;
ll a[100005];
int main(){
    cin>>n>>m;
    for(int i=0;i<n;i++)cin>>a[i];
    ll p=0;
    for(int i=0;i<n;i++){
        p+=a[i];
        if(p>m){
            cnt++;
            p=a[i];
        }
    }
    cout<<cnt;
    return 0;
}

H. 「一本通 1.1 练习 3」线段 

题目描述

数轴上有 �n 条线段,选取其中 �k 条线段使得这 �k 条线段两两没有重合部分,问 �k 最大为多少。

输入格式

第一行为一个正整数 �n;

在接下来的 �n 行中,每行有 22 个数 ��,��ai​,bi​,描述每条线段。

输出格式

输出一个整数,为 �k 的最大值。

样例

输入数据 1

3
0 2
2 4
1 3

Copy

输出数据 1

2

Copy

数据范围与提示

对于 20%20% 的数据,�≤10n≤10;

对于 50%50% 的数据,�≤103n≤103;

对于 70%70% 的数据,�≤105n≤105;

对于 100%100% 的数据,�≤106,n≤106, 0≤��<��≤1060≤ai​<bi​≤106。

 

是不是感觉写过?没错就是同类型题 

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int n,cnt,p;
struct app{
    int l,r;
}a[1000005];
bool cmp(app x,app y){//右端点排序
    return x.r<y.r;
}
int main(){
    cin>>n;
    for(int i=0;i<n;i++){
        cin>>a[i].l>>a[i].r;
    }
    sort(a,a+n,cmp);
    for(int i=1;i<n;i++){
        if(a[i].l>=a[p].r){
            cnt++;
            p=i;
        }
    }
    cout<<cnt+1;
    return 0;
}

I. 「一本通 1.1 练习 4」家庭作业 

题目描述

老师在开学第一天就把所有作业都布置了,每个作业如果在规定的时间内交上来的话才有学分。每个作业的截止日期和学分可能是不同的。例如如果一个作业学分为 1010,要求在 66 天内交,那么要想拿到这 1010 学分,就必须在第 66 天结束前交。

每个作业的完成时间都是只有一天。例如,假设有 7 次作业的学分和完成时间如下:

作业号期限学分
111166
2277
333322
4411
552244
6655
776611

最多可以获得 1515 学分,其中一个完成作业的次序为 2,6,3,1,7,5,42,6,3,1,7,5,4,注意可能还有其他方法。

你的任务就是找到一个完成作业的顺序获得最大学分。

输入格式

第一行一个整数 �N,表示作业的数量;

接下来 �N 行,每行包括两个整数,第一个整数表示作业的完成期限,第二个数表示该作业的学分。

输出格式

输出一个整数表示可以获得的最大学分。保证答案不超过 C/C++ 的 int 范围。

样例

输入数据 1

7
1 6
1 7
3 2
3 1
2 4
2 5
6 1

Copy

输出数据 1

15

Copy

数据范围与提示

对于 20%20% 的数据,�≤103N≤103;

对于 40%40% 的数据,�≤104N≤104;

对于 60%60% 的数据,�≤105N≤105;

对于 100%100% 的数据,�≤106N≤106,作业的完成期限均小于 7×1057×105。

 

贪心思想O(n),从第一天枚举到最后一天太难判断了也不好选择,所以我们倒过来从最后一天开始往前面选

分两种情况

假如最后一天期限的数量到前一天的数量不冲突,直接都选即可

 

假设存在冲突的,就需要比较大小 

 

 所以开一个优先队列来记录大小即可

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int n;
ll ans;
struct app{
    int t,f;
}a[1000005];
priority_queue<int,vector<int>,less<>>pq;
bool cmp(app x,app y){//按照最大时间排序
    if(x.t!=y.t)return x.t>y.t;
    return x.f>y.f;
}
int main(){
    cin>>n;
    int ppx=0;
    for(int i=0;i<n;i++){
        cin>>a[i].t>>a[i].f;
        ppx=max(ppx,a[i].t);//找到最后的时间期限
    }
    sort(a,a+n,cmp);
    int p=0;
    for(int i=ppx;i>=1;i--){//从最后一天枚举到第一天
        while(i==a[p].t&&p<n){//只要存在期限等于i的都加进去,当然最多也就n个
            pq.push(a[p].f);
            p++;
        }
        if(pq.size()){//只要队列不为空,就把里面学分最大的拿到手
            ans+=pq.top();
            pq.pop();
        }
    }
    cout<<ans;
    return 0;
}

J. 「一本通 1.1 练习 5」钓鱼 

题目描述

在一条水平路边,有 �n 个钓鱼湖,从左到右编号为 1,2,…,�1,2,…,n。佳佳有 �H 个小时的空余时间,他希望利用这个时间钓到更多的鱼。他从 11 出发,向右走,有选择的在一些湖边停留一定的时间(是 55 分钟的倍数)钓鱼。最后在某一个湖边结束钓鱼。佳佳从第 �i 个湖到第 �+1i+1 个湖需要走 5×��5×Ti​ 分钟路,还测出在第 �i 个湖停留,第一个 55 分钟可以钓到 ��Fi​ 条鱼,以后每再钓 55 分钟,可以钓到的鱼量减少 ��Di​,若减少后的鱼量小于 00,则减少后的鱼量为 00 。为了简化问题,佳佳假定没有其他人钓鱼,也没有其他因素影响他钓到期望数量的鱼。请编程求出佳佳最多能钓鱼的数量。

输入格式

第一行一个整数 �n,表示湖的个数

第二行一个整数 �H,表示佳佳的空闲时间

第三行有 �n 个整数,依次表示每个湖第一个 55 分钟能钓到鱼的数量

第四行有 �n 个整数,依次表示以后的每5分钟钓鱼数量比前一个 55 分钟钓鱼数量减少的数量

第五行有 �−1n−1 个整数,��Ti​ 表示由第 �i 个湖到第 �+1i+1 个湖需要花 5×��5×Ti​ 分钟的路程

输出格式

输出只有一行,表示佳佳最多能钓鱼的数量。

样例

输入数据 1

3
1
4 5 6
1 2 1
1 2

Copy

输出数据 1

35

Copy

在第 11 个湖钓 1515 分钟,共钓得 4+3+2=94+3+2=9 条鱼;

在第 22 个湖钓 1010 分钟,共钓得 5+3=85+3=8条鱼;

在第 33 个湖钓 2020 分钟,共钓得 6+5+4+3=186+5+4+3=18 条鱼;

从第 11 个湖到第 22 个湖,从第 22 个湖到第 33 个湖,共用时间 1515 分钟,共得 3535 条鱼,并且这是最多的数量。

数据范围与提示

对于 100%100% 的数据,2≤�≤100,1≤�≤202≤n≤100,1≤H≤20。

 

贪心+优先队列

由于题目已经说了是从1开始,往右走,所以我们记录当他走到每个湖时能钓到鱼的最大数量,然后比较取出最大值即可

#include<bits/stdc++.h>
using namespace std;
int a[105], b[105], t[105];
priority_queue<pair<int,int>, vector<pair<int,int> >, less<>>pq;
int main() {
    int n, m;
    cin >> n >> m;
    m = m * 60 / 5;//表示五分钟的个数
    for (int i = 0; i < n; i++){
        cin >> a[i];
    }
    for (int i = 0; i < n; i++){
        cin >> b[i];
        
    }
    for(int i=1;i<n;i++){
        cin>>t[i];
    }
    int ans = 0;
    for (int i = 0; i < n; i++) {
        m -= t[i];//走到第i个湖时减去走路所需的时间
        if(m<=0)break;//没有操作数直接打破循环
        int pp=m;
        for(int j=0;j<=i;j++){if(a[i]>0)pq.push({a[j],b[j]});}//将几个湖的初始和减少量加入
        int cnt=0;
        while(pp--){
            int t=pq.top().first;
            int tt=pq.top().second;
            cnt+=t;
            pq.pop();
            if(t-tt>0)pq.push({t-tt,tt});//还能减就加入队列
            if(pq.empty())break;//队列空了
        }
        while(pq.size())pq.pop();//如果队列没空,就清空队列
        ans=max(ans,cnt);
    }
    cout<<ans;
}

 

 

 

 

 

 

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值