http://acm.hdu.edu.cn/showproblem.php?pid=6180
贪心的策略是 让每份时间的间隔尽可能的小。
1 维护一个 multiset,里面放的是各个机器的最后运行时间。
然后每一个时间段,查找最近的比这个时间段时间小的 机器最后时间,如果没有的话,即所有的最后运行时间都比他的大,那么就再开一个机器,否则的话,把最近的那个机器时间给更新了,然后继续。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
bool cmp2(pii a,pii b){
return a.first<b.first;
}
vector<pii>q;
multiset<int>se;
int main()
{ int t,m,a,b;
scanf("%d",&t);
while(t--){
scanf("%d",&m);
q.clear();
se.clear();
ll sum=0;
for(int i=0;i<m;i++){
scanf("%d%d",&a,&b);
q.push_back(make_pair(a,b));
}
sort(q.begin(),q.end(),cmp2);
for(int i=0;i<m;i++){
multiset<int>::iterator p=se.upper_bound(q[i].first);
if(p==se.begin()){
//只能开一个机器了,所有机器的时间都比他的结束。。
sum+=1ll*(q[i].second-q[i].first);
se.insert(q[i].second);
}
else{ p--;
sum+=1ll*(q[i].second-*p);
se.erase(p);
se.insert(q[i].second);
}
// cout<<sum<<endl;
}
printf("%d %lld\n",se.size(),sum);
}
return 0;
}
另一种方法,大概理解,但是不太明白原理。。先mark。
每个机器的时间段 画成一个横线。
#include<stdio.h>
#include<algorithm>
using namespace std;
#define LL long long
typedef struct
{
LL x;
LL flag;
}Point;
Point s[200005];
LL L[100005], R[100005];
bool comp(Point a, Point b)
{
if(a.x<b.x || a.x==b.x && a.flag<b.flag)
return 1;
return 0;
}
int main(void)
{
LL T, n, i, a, b, sum, ans;
scanf("%lld", &T);
while(T--)
{
scanf("%lld", &n);
for(i=1;i<=n;i++)
{
scanf("%lld%lld", &a, &b);
s[i*2-1].x = a, s[i*2-1].flag = 1;
s[i*2].x = b, s[i*2].flag = -1;
}
n *= 2;
sort(s+1, s+n+1, comp);
sum = ans = 0;
for(i=1;i<=n;i++)
{
sum += s[i].flag;
if(sum>ans)
{
ans = sum;
L[sum] = s[i].x;
}
ans = max(ans, sum);
}
sum = ans = 0;
for(i=n;i>=1;i--)
{
sum -= s[i].flag;
if(sum>ans)
{
ans = sum;
R[sum] = s[i].x;
}
ans = max(ans, sum);
}
sum = 0;
for(i=1;i<=ans;i++)
sum += R[i]-L[i];
printf("%lld %lld\n", ans, sum);
}
return 0;