1. 程式人生 > >【貪心】hdu6180 Schedule

【貪心】hdu6180 Schedule

set highlight log memset space else con scanf 開始

題意:給你n個任務的開始時間和結束時間,一個機器同時最多執行一個任務,問你最少要幾個機器。保證機器最少的前提下,問你每個機器的開動時間(最後一次關閉-第一次開啟)之和最少是多少。

把這些線段畫在數軸上,最大的重疊數就是最少要幾個機器。

開動時間怎麽算呢?第i個機器的開動時間其實就是(再也不需要>=i臺機器的第一個位置 - 需要>=i臺機器的第一個位置)。對每個機器的這個值求和即可。

要先離散化。

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
struct Point{
	int p,v;
}t[200005];
bool cmp(const Point &a,const Point &b)
{
	return a.v<b.v;
}
int T,n;
int xs[100005],ys[100005],a[200005],ma[200005],Left[200005],Right[200005];
int sufmax[200005];
int main(){
	//freopen("1010.in","r",stdin);
	scanf("%d",&T);
	for(;T;--T){
		memset(a,0,sizeof(a));
		memset(ma,0,sizeof(ma));
		memset(Left,0x7f,sizeof(Left));
		memset(Right,0,sizeof(Right));
		memset(sufmax,0,sizeof(sufmax));
		int all=0;
		scanf("%d",&n);
		for(int i=1;i<=n;++i){
			++all;
			scanf("%d",&t[all].v);
			t[all].p=all;
			++all;
			scanf("%d",&t[all].v);
			t[all].p=all;
		}
		sort(t+1,t+all+1,cmp);
		int zy=0;
		if(t[1].p%2==1){
			xs[(t[1].p+1)/2]=++zy;
		}
		else{
			ys[t[1].p/2]=++zy;
		}
		ma[zy]=t[1].v;
		for(int i=2;i<=all;++i){
			if(t[i].v!=t[i-1].v){
				++zy;
			}
			if(t[i].p%2==1){
				xs[(t[i].p+1)/2]=zy;
			}
			else{
				ys[t[i].p/2]=zy;
			}
			ma[zy]=t[i].v;
		}
		for(int i=1;i<=n;++i){
			++a[xs[i]];
			--a[ys[i]];
		}
		for(int i=1;i<=zy;++i){
			a[i]+=a[i-1];
		}
		sufmax[zy]=a[zy];
		for(int i=zy-1;i>=1;--i){
			sufmax[i]=max(a[i],sufmax[i+1]);
		}
		int ans=*max_element(a+1,a+zy+1);
		for(int i=1;i<=zy;++i){
			if(Left[a[i]]>2000000000){
				Left[a[i]]=i;
			}
		}
		for(int i=ans-1;i>=1;--i){
			Left[i]=min(Left[i],Left[i+1]);
		}
		for(int i=zy;i>=1;--i){
			if(sufmax[i]!=sufmax[i-1]){
				for(int j=sufmax[i]+1;j<=sufmax[i-1];++j){
					Right[j]=i;
				}
			}
		}
		ll sum=0;
		for(int i=1;i<=ans;++i){
			sum+=(ll)(ma[Right[i]]-ma[Left[i]]);
		}
		printf("%d %lld\n",ans,sum);
	}
	return 0;
}

【貪心】hdu6180 Schedule