【差分】会场安排问题

很久很久以前的东西了。。

那时候是弱菜中的弱菜(现在是弱菜),这篇文章我也不改什么。。

«问题描述:假设要在足够多的会场里安排一批活动,并希望使用尽可能少的会场。设计一个有效的贪心算法进行安排。(这个问题实际上是著名的图着色问题。若将每一个活动作为图的一个顶点,不相容活动间用边相连。使相邻顶点着有不同颜色的最小着色数,相应于要找的最小

会场数。)

«编程任务:对于给定的k个待安排的活动,编程计算使用最少会场的时间表。«数据输入:由文件input.txt给出输入数据。第一行有1 个正整数k,表示有k个待安排的活动。接下来的k行中,每行有2个正整数,分别表示k个待安排的活动开始时间和结束时间。时间以0 点开始的分钟计。«结果输出:将编程计算出的最少会场数输出到文件output.txt。输入文件示例 输出文件示例input.txt  output.txt5              31 2312 2825 3527 80

36 50

(CJMXHLXW)

这道题是我们考试的一道题,当时我看到就懵逼,考试考的是贪心分治,可是我考试的时候做别的难题去了,越做越烦,做这题时贪心都没贪出来,结果那次考试爆0,尴尬了《【差分】会场安排问题》

考试完题目总是要讲解的嘛,黄司机A掉了这道题,这道题先是他上去讲解贪心算法,时间复杂度为O(n^2)。

第二天,wen大神又来为我们讲解了某种高级算法——好像提到了差分数组《【差分】会场安排问题》,我居然听懂了《【差分】会场安排问题》。而且还心血来潮,写了个题解。=_=

首先搞懂这个“差分数组”,我们用到的主要功能就是在某个集合里,在[L,R]这个区间内,把每个数都加上k,用我们普通的算法肯定是for一遍,这样如果有n个数,要m次操作,那么时间复杂度就是O(mn),而这道题的范围n有10^8,m有10^4,显然这是不行的。这里wen大神介绍了一种新的数据结构——差分数组。把[L,R]区间里都加上k,只需要把a[L]加上k,再把a[R+1]减去k就行了,当时听了也不懂,这样后求L~R区间的和不是只加了1个k吗。原来求和的sum[i]加到a[L]时,值为k,加了a[R+1]后,又变为0,我们就可以理解为[L,R]区间里都加了k。还有这种操作?《【差分】会场安排问题》《【差分】会场安排问题》当然这道题集合的范围有10^8,而我们不可能开个10^8的数组,所以我们可以先sort一遍,然后把集合压缩,把每个数取第一次出现的次数,就拿样例来说吧,sort后为1  12 23 25 27 28 35 36 50 80,直接对应1,2,3,4,5,6,7,8,9,10,我们直接按之前说的操作,把数改成下标就行了。

《【差分】会场安排问题》

好了,上代码

#include <iostream>
#include <map>
using namespace std;
int a[100010],b[100010],c[100010],d[100010],n,now,sum,Max;
map<int,int>e;
int main(){
	freopen("sche.in","r",stdin);
	freopen("sche.out","w",stdout);
	cin>>n;
	for(int i=1;i<=n;i++){
       scanf("%d%d",&a[i],&b[i]);
       c[2*i-1]=a[i];
       c[2*i]=b[i];
    }
    sort(c+1,c+2*n+1);
    for(int i=1;i<=2*n;i++)
       if(!e[c[i]])
         e[c[i]]=++now;
    for(int i=1;i<=n;i++)
       d[e[a[i]]]++,
       d[e[b[i]]]--;
    for(int i=1;i<=now+1;i++)
       sum+=d[i],
       Max=max(Max,sum);
    cout<<Max;
	fclose(stdin);
	fclose(stdout);
	//system("pause");
	return 0;
}


点赞