AcWing基础算法课Level-2 第六讲 贪心

AcWing基础算法课Level-2  第六讲 贪心_i++

区间问题
AcWing 905. 区间选点1751人打卡
AcWing 908. 最大不相交区间数量1613人打卡
AcWing 906. 区间分组1414人打卡
AcWing 907. 区间覆盖1321人打卡
Huffman树
AcWing 148. 合并果子1491人打卡
排序不等式
AcWing 913. 排队打水1399人打卡
绝对值不等式
AcWing 104. 货仓选址1448人打卡
推公式
AcWing 125. 耍杂技的牛

代码

AcWing 905. 区间选点

//题意:n个区间,选出尽可能少的点,让每个区间包含至少一个点。求点数。
//思路:考虑排序后尽可能往右放。将区间按右端点从小到大排序,在当前区间右端点放一个点并往下枚举,当下一个区间的左端点无法覆盖它时则新建一个点放在右端点。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+10;
struct node{int l,r;}a[maxn];
bool cmp(node a, node b){return a.r<b.r;}
int main(){
int n; cin>>n;
for(int i = 1; i <= n; i++)
cin>>a[i].l>>a[i].r;
sort(a+1,a+n+1,cmp);
int cnt = 1, t = a[1].r;
for(int i = 2; i <= n; i++){
if(a[i].l>t){
cnt++;
t = a[i].r;
}
}
cout<<cnt<<"\n";
return 0;
}

AcWing 908. 最大不相交区间数量

//题意:n个区间,选出若干个区间,满足它们互不相交。
//思路:和上一题一模一样,考虑排序后尽可能往右放。将区间按右端点从小到大排序,首先选中第一个区间并往下枚举,当下一个区间的左端点无法覆盖它时则选择那个区间,因为此时那个区间离他是最近的。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+10;
struct node{int l,r;}a[maxn];
bool cmp(node a, node b){return a.r<b.r;}
int main(){
int n; cin>>n;
for(int i = 1; i <= n; i++)
cin>>a[i].l>>a[i].r;
sort(a+1,a+n+1,cmp);
int cnt = 1, t = a[1].r;
for(int i = 2; i <= n; i++){
if(a[i].l>t){
cnt++;
t = a[i].r;
}
}
cout<<cnt<<"\n";
return 0;
}

AcWing 906. 区间分组

//题意:区间厚度的问题或教室安排问题,n个区间,若干个区间一组并满足组内互不相交,求最少分多少个组。
//思路:把所有开始和结束时间丢在一起排序,遇到开始的就+1,结束的就-1,过程中的最大值就是最少分组(厚度和占用)。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+10;
int a[maxn<<1];
int main(){
int n; cin>>n;
for(int i = 1; i <= n; i++){
int l, r; cin>>l>>r;
a[i] = l<<1; a[i+n]=r<<1|1;//用奇偶数区分左右端点
}
sort(a+1,a+2*n+1);
int cnt = 0, ans=-1;
for(int i = 1; i <= 2*n; i++){
if(a[i]%2==0)cnt++;
else cnt--;
ans = max(ans,cnt);
}
cout<<ans<<"\n";
return 0;
}

AcWing 907. 区间覆盖

//题意:n个区间,求最少选出多少个区间可以覆盖目标区间[s,t]
//思路:将区间按左端点排序,选中第一个区间并往后枚举,在所有与当前区间相连的区间中,选择右端点最大的,然后重复。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+10;
struct node{int l,r;}a[maxn];
bool cmp(node a, node b){return a.l<b.l;}
int main(){
int s, t; cin>>s>>t;
int n; cin>>n;
for(int i = 1; i <= n; i++)
cin>>a[i].l>>a[i].r;
sort(a+1,a+n+1,cmp);
int ans = 0, ok = 0;
for(int i = 1; i <= n; i++){
int j = i, r = -1e9;
while(j<=n && a[j].l<=s){
r = max(r,a[j].r); j++;
}
ans++;
if(r<s){ans = -1; break;}
if(r>=t){ ok = 1; break;}
s = r;
i = j-1;
}
if(ok==1)cout<<ans<<"\n";
else cout<<-1<<"\n";
return 0;
}

AcWing 148. 合并果子

#include<iostream>
#include<queue>
using namespace std;
priority_queue<int, vector<int>, greater<int> >q;
int main(){
int n, ans = 0; cin>>n;
for(int i = 0; i < n; i++){
int a; cin>>a; q.push(a);
}
for(int i = 0; i < n-1; i++){
int a = q.top(); q.pop();
int b = q.top(); q.pop();
ans += a+b; q.push(a+b);
}
cout<<ans;
return 0;
}

AcWing 913. 排队打水

//题意:1个水龙头,n个人打水,每个人需要ti时间,求最少的总等待时间。
//思路:贪心,越前面打水的后面的每个人都要等,所以让打的快的先打。
#include<bits/stdc++.h>
typedef long long LL;
using namespace std;
const int maxn = 1e5+10;
LL a[maxn];
int main(){
int n; cin>>n;
for(int i = 1; i <= n; i++)cin>>a[i];
sort(a+1,a+n+1);
LL ans = 0, cnt = 0;
for(int i = 1; i <= n; i++){
ans += cnt;
cnt += a[i];
}
cout<<ans<<"\n";
return 0;
}

AcWing 104. 货仓选址

//题意:一条数轴上n个点,坐标a[i]。求放置一个点x,使得sum(x-a[i])的值最小。
//思路:设在仓库左边的所有点,到仓库的距离之和为p,右边的距离之和则为q,所求即为让p+q的值尽量小。当仓库向左移动的话,p会减少x,但是q会增加n−x,所以当为仓库中位数的时候,p+q最小。
#include<bits/stdc++.h>
typedef long long LL;
using namespace std;
const int maxn = 1e5+10;
LL a[maxn];
int main(){
int n; cin>>n;
for(int i = 1; i <= n; i++)cin>>a[i];
sort(a+1,a+n+1);
int mid = a[n/2+1]; //中位数
int ans = 0;
for(int i = 1; i <= n; i++)
ans += abs(a[i]-mid);
cout<<ans<<"\n";
return 0;
}

AcWing 125. 耍杂技的牛

//题意:n头牛,每头牛有重量wi和强壮si,对奶牛进行排序,使得每头牛的风险值(前面所有wi之和减去他的si)最大的尽可能小。
//思路:考虑交换第i头牛和i+1头牛,可以发现,当wi+si>=w[i+1]+s[i+1]时交换后更优,所以直接排序.
#include<bits/stdc++.h>
typedef long long LL;
using namespace std;
const int maxn = 5e5+10;
struct node{LL w,s;}a[maxn];
bool cmp(node a, node b){
return a.w+a.s<b.w+b.s;
}
int main(){
int n; cin>>n;
for(int i = 1; i <= n; i++)
cin>>a[i].w>>a[i].s;
sort(a+1,a+n+1,cmp);
LL ans = -1e18, sum = 0;
for(int i = 1; i <= n; i++){
ans = max(ans,sum-a[i].s);
sum += a[i].w;
}
cout<<ans<<"\n";
return 0;
}