多校10_1010 hdu6180 贪心+STL:multiset

0.0

//出处:2017多校10 1010  hdu6180 
//题意:给出N个工作区间,一台机器一个时间段内只能做一个任务,问最小机器数完成所有任务以及最短机器开机时间 
//思路:按开始时间排序贪心, 遍历所有start:multiset存储结束时间, 找出当前start最近的end:t1,找到就更新t1的end(删掉再插入),找不到就新开一台机器。 
//注意:(遍历所有start的时候千万不能先进先入!!要考虑所有机器当前的end,所以以前的老方法不行= =),
//查找要用multiset的二分成员函数lower_bound,反向迭代器查找会超时.因为是要找最大的end,所以存的时候存负数配合lower_bound 
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<vector>
#include<string>
#include<string.h>
#include<ctype.h>
#include<set> 
#include<math.h>
#include<map>
#include<iterator>
#define INF 0x3f3f3f3f
#define e 2.718281828459
#define MaxN 100000
#define scann(d) scanf("%d",&d)
using namespace std;
typedef  long long int ll;
inline ll gcd(ll a,ll b)
{
	return a==0?b:gcd(b%a,a);
}
inline int b_s1(int *a,int l,int r,int k); 		//   二分查找 [l,r)找k 找到返回下标 O(log(n));
inline void Fill(int *a,int *b,int c); 			//填充数组
inline ll mod_pow(ll x,ll n,ll mod); 			//快速幂 余数

void init()
{

}

void solve(int n)
{

}
struct point
{
	int start;
	int end;
	point(int a,int b)
	{
		start=a;
		end=b;
	}
};
vector<point>ps;
bool vis[100005];
bool cmp(point a,point b)
{
	if(a.start!=b.start)
		return a.start<b.start;
	else
		return a.end>b.end;
}
int main()
{
	int T;
	scanf("%d",&T);
	while(T--)
	{
		int n;ll sum=0;
		int a,b;
		scanf("%d",&n);
		ps.clear();
		multiset<int>ms1;
		ms1.clear();
		for(int i=0; i<n; i++)
		{
			scanf("%d %d",&a,&b);
			vis[i]=true;
			//sum+=(b-a);
			ps.push_back(point(a,b));
		}
		sort(ps.begin(),ps.end(),cmp);
		/*/test output
			for(int i=0;i<ps.size();i++)
			{
				cout<<ps[i].start<<" "<<ps[i].end<<endl;
			}
		//*/
		int K=0;
		for(int i=0; i<ps.size(); i++)
		{
			if(ms1.empty())
			{
				ms1.insert(-ps[0].end);
				sum+=ps[0].end-ps[0].start;
				continue;
			}
			int flag=0;
		/*	/too slow
		for(multiset<int>::reverse_iterator poi=ms1.rbegin();poi!=ms1.rend();poi++)
			{
				if(*poi<=ps[i].start)
				{
					multiset<int>::iterator poj=poi.base();
					flag=1;
					int t=*poi;
					ms1.erase(--poj);
					sum+=ps[i].end-t;
					//cout<<"sum:"<<sum<<" i:"<<i<<endl;
					break;
				}
			}
			//*/
			multiset<int>::iterator poi=ms1.lower_bound(-ps[i].start);
			if(poi!=ms1.end())//找到了! 
			{
				ms1.insert(-ps[i].end);
				ms1.erase(poi);
				sum+=ps[i].end+*poi;
			}
			else//只能新开机器了0.0 
			{
			//	cout<<"sum:"<<sum<<" i:"<<i<<endl;
				ms1.insert(-ps[i].end);
				sum+=ps[i].end-ps[i].start;
			}


		}
		printf("%d %I64d\n",ms1.size(),sum);
	}


	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值