题目链接 :HDU 3650 Hot Expo
【题目大意】
Sunny在逛上海世博会,世博会有很多国家的场,每个场子每天同一时段都有一场精彩的表演。表演开始时间 为beg,结束时间为 end ,Sunny有强迫症,他想要看完所有给定表演,并且一秒钟 都不拉下,也就是说 ,表演一 beg =1 end =4 表演二 beg = 4 ,end =5.那么为了完整的看表演二,Sunny需要在第二天再来看 表演二。
现在给出所有表演的 beg end,让你求出Sunny看完所有表演所花的全部天数。
这个题和气球染色的如出一辙。
给定区间,将区间的气球染色一次。问最后区间内的哪个气球染色次数最多,输出最大的染色次数。
用paint【1~n】 表示每个气球的染色次数,初始化为0;
很容易想到,每次染色,将区间【i,j】 全部加1。 最后查询从头到尾遍历一遍找到最大的paint【i】就可以了。
这个题目由于数据规模小可以直接这样做。
当数据规模较大的时候,每次染色的最大消耗将是 从0~n;
这里学到了一个巧妙地办法
为区间 【i, j】 染色,我们只要将 paint【i】++ ;paint【j+1】-- ;统计染色次数只要从0向终点求和即可,复杂度为O(n)。
直接这样描述不好懂,我们来举个栗子。
给定区间 1 - 4 ,染色后:
i: 1 2 3 4 5 6 7
paint【i】:1 0 0 0 -1 0 0
可以看出 sum【1】 =1 , sum【2】 =1 ,sum【3】 =1,sum【4】 = 1,sum【5】 = 0;
给定区间 4 - 6 ,染色后:
i: 1 2 3 4 5 6 7
paint【i】:1 0 0 0 0 0 -1
这时,sum【1】 =1 , sum【2】 =1 ,sum【3】 =1,sum【4】 = 1,sum【5】 = 1,sum【6】 = 1, sum【7】=0;
这样我们就实现了只用给 paint【i】和paint【j+1】 赋值 ,就实现了染色次数的统计 。 省去了O(n)时间的染色阶段。
【普通的染色方法】
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 24*3610;
int ans[maxn];
int main(){
int n;
while(scanf("%d",&n)!=EOF&&n){
int a,b;
memset(ans,0,sizeof(ans));
int begin = 1,end=1;
for(int i=0;i<n;i++){
scanf("%d%d",&a,&b);
if(b>end)
end = b;
for(int j=a;j<=b;j++){
ans[j]++;
}
}
int maxx =1;
for(int i=0;i<=end;i++){
maxx = max(maxx,ans[i]);
}
printf("%d\n",maxx);
}
return 0;
}
【欧阳大神教的染色方法】
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 24*3610;
int paint[maxn];
int main(){
int n;
while(scanf("%d",&n)!=EOF && n){
int a,b;
int maxx = 1;
memset(paint,0,sizeof(paint));
for(int i=0;i<n;i++){
scanf("%d%d",&a,&b);
if(b>maxx)
maxx = b;
paint[a]++;
paint[b+1]--;
}
int sum = 0;
int ans = 0;
for(int i=0;i<=maxx;i++){
sum += paint[i];
ans = max(sum,ans);
}
printf("%d\n",ans);
}
return 0;
}
【这里还有个贪心的算法】
开始我是按照演出结束时间排序的WA了,以开始时间排序AC了,还没有想明白为什么。希望各路大神的指点
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<cctype>
#include<set>
#include<vector>
const int maxn = 110;
using namespace std;
string num[maxn];
bool vis[maxn];
struct Node{
int x,y;
}node[maxn];
bool cmp(const Node&a, const Node&b){
if(a.x == b.x)
return a.y<b.y;
return a.x<b.x; //以开始时间小的排序
}
int main(){
int n;
while(scanf("%d",&n)!=EOF &&n){
for(int i=0;i<n;i++){
scanf("%d%d",&node[i].x,&node[i].y);
}
memset(vis,0,sizeof(vis));
sort(node,node+n,cmp);
int sign = n;
int ed = 0;
int day = 0;
while(sign){
day ++;
vis[ed] = 1;
sign--;
int tmpx = node[ed].y;
for(int i=0;i<n;i++){
if(!vis[i] && node[i].x>tmpx){
vis[i] = 1;
tmpx = node[i].y;
sign--;
}
}
for(int i=0;i<n;i++){
if(!vis[i]){
ed = i;break;
}
}
}
printf("%d\n",day);
}
return 0;
}