- 题目大意
有n个任务,每个任务有一个起始时间和终止时间,一台机器一个时间最多处理一个任务,一台机器的运行时间定义为这台机器处理的任务中第一个任务开始的时间到最后一个任务结束的时间。
问你最少需要多少台机器,在最少机器数量的情况下所有机器总的时间花费是多少. 分析
这种区间任务调度问题通常可行的一种实现方式是将左右端点看成独立的点来处理(用01来表示是左端点还是右端点),排一次序依次处理。
符号约定
total :记录在扫描的过程中当前开启的机器数目
now :记录当前正在使用的机器数
那么我们可以得到这样的贪心策略- 如果遇到的是左端点:
- if(total==now)total++;now++; //当前已经开启的机全在使用,这个时候就需要新开一台
- if(total>now)now++; //有空闲的机器就使用空闲的机器
- 如果遇到的是右端点:
now−−
这样我们就可以找到最少的机器数
总的花费时间就是每台机器的结束时间之和减去每台机器的开始时间之和
有一条贪心策略就是当有空闲的机器可用时我们用结束最晚的那个
在每次新开机器的时候我们记录下开启的时间就可以得到总的开启时间
我们用一个栈来保存有机器空出时的结束时间,并在有新任务给空闲机器的时候将栈顶弹出(也就是结束时间最晚的那个),最后栈中的元素就一定是全部开启的机器的结束时间了- 如果遇到的是左端点:
代码
#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<queue>
#include<map>
#include<algorithm>
#include<set>
#include<stack>
using namespace std;
#define LL long long int
const int MAXN=200055;
int T;
LL n;
LL total;
LL now;
LL sum_start_time;
LL sum_end_time;
struct Node
{
LL x;
bool is_head;
}node[MAXN];
int nodecount;
inline void getInt(int* p) {
char ch;
do {
ch = getchar();
} while (ch == ' ' || ch == '\n');
if (ch == '-') {
*p = -(getchar() - '0');
while ((ch = getchar()) >= '0' && ch <= '9') {
*p = *p * 10 - ch + '0';
}
}
else {
*p = ch - '0';
while ((ch = getchar()) >= '0' && ch <= '9') {
*p = *p * 10 + ch - '0';
}
}
}
void Init()
{
nodecount=0;
total=0;
now=0;
sum_start_time=0;
sum_end_time=0;
}
void Add_node(LL x,bool is_head)
{
node[++nodecount].x=x;
if(is_head==1)node[nodecount].is_head=1;
else node[nodecount].is_head=0;
}
int cmp(Node a,Node b)
{
if(a.x!=b.x)return a.x < b.x;
else return a.is_head < b.is_head;
}
void In()
{
int s,t;
scanf("%lld",&n);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&s,&t);
//getInt(&s);getInt(&t);
Add_node(s,1);
Add_node(t,0);
}
}
void Work()
{
stack<LL> St;
sort(node+1,node+2*n+1,cmp);
for(int i=1;i<=2*n;i++)
{
if(node[i].is_head==0)
{
now--;
St.push(node[i].x);
}
else
{
if(total==now){total++;now++;sum_start_time+=node[i].x;}
else {now++;St.pop();}
}
}
while(!St.empty())
{
LL t=St.top();
St.pop();
sum_end_time+=t;
}
printf("%lld %lld\n",total,sum_end_time-sum_start_time);
}
int main()
{
//freopen("in.txt","r",stdin);
// freopen("out1.txt","w",stdout);
scanf("%d",&T);
while(T--)
{
Init();
In();
Work();
}
return 0;
}
/*
2
3
1 3
4 6
2 5
2
1 1000000000
1 1000000000
*/