习题:Kisik(贪心)
题目:
银河国家殖民地联盟(CAIN)决定在火星上为K个家庭建造一座城市,因此,必须要为每个家庭建造一座房子,即一共K座房子。对于每个家庭,将可以选择从银河系最好的建筑师准备的N种建筑中选择一种。对于所有的建筑物,都是矩形,第i种建筑宽Wi,高Hi。此外,由于CAIN推广各种品种,所有的家庭将获得不同的设计。
各个建筑彼此相邻建造,因此,他们的底部位于同一条线上。建成后,因为城市需要充满空气,因此这个城市将被一个巨大的玻璃墙包围,将空气保持在里面。玻璃墙也是矩形形状,其侧面平行于建筑物侧面。
由于保持火星上的空气价格十分昂贵,因此您的工作就是在所有可能中选择空气最少(即玻璃墙包围面积最小)的方案。
输入格式
第一行输入2个数字N,K(1≤K≤N≤1000000),表示房屋类型的种类和总共的户数。
接下来N行,每行输入两个数字Wi,Hi(1≤Wi,Hi≤1000000),用空格隔开,表示第i种房屋类型的宽和高。
输出格式
输出一个数字,表示最少需要的空气量。
样例
样例输入1
4 3
2 3
2 2
1 4
3 2
样例输出1
20
样例输入2
3 3
1 1
3 3
2 2
样例输出2
18
样例输入3
4 1
6 4
4 5
19 1
3 6
样例输出3
18
思路:
考虑到每一个矩阵的计算,宽一定是选的所有房子的最大值,长一定是选的是所有矩阵的宽的和,那么我们自然而然地就可以讲到贪心策略,对于每一个高,我们只需将宽最小即可,考虑
将宽保证最小即可,那么维护这个最小值自然而然就想到可以用优先队列来维护。
代码:
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
long long n,k;
long long s;
long long ans=1ll*1000000*1000000*1000000+5;
pair<long long,long long> b[1000005];
priority_queue<long long> q;
int main()
{
cin>>n>>k;
for(int i=1;i<=n;i++)
{
cin>>b[i].fi>>b[i].se;
swap(b[i].fi,b[i].se);
}
sort(b+1,b+n+1);
for(int i=1;i<=k;i++)
{
s+=b[i].se;
q.push(b[i].se);
}
for(int i=k;i<=n;i++)
{
ans=min(ans,s*b[i].fi);
//cout<<ans<<endl;
s+=b[i+1].se;
q.push(b[i+1].se);
s-=q.top();
q.pop();
}
cout<<ans;
return 0;
}