湫湫系列故事——减肥记II
Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)Total Submission(s): 1263 Accepted Submission(s): 537
Problem Description
虽然制定了减肥食谱,但是湫湫显然克制不住吃货的本能,根本没有按照食谱行动!
于是,结果显而易见…
但是没有什么能难倒高智商美女湫湫的,她决定另寻对策——吃没关系,咱吃进去再运动运动消耗掉不就好了?
湫湫在内心咆哮:“我真是天才啊~\(≧▽≦)/~”
可是,大家要知道,过年回家多忙啊——帮忙家里做大扫除,看电影,看小说,高中同学聚餐,初中同学聚餐,小学同学聚餐,吃东西,睡觉,吃东西,睡觉,吃东西,睡觉……所以锻炼得抽着时间来。
但是,湫湫实在太忙了,所以没时间去算一天有多少时间可以用于锻炼,现在她把每日行程告诉你,拜托你帮忙算算吧~
皮埃斯:一天是24小时,每小时60分钟
于是,结果显而易见…
但是没有什么能难倒高智商美女湫湫的,她决定另寻对策——吃没关系,咱吃进去再运动运动消耗掉不就好了?
湫湫在内心咆哮:“我真是天才啊~\(≧▽≦)/~”
可是,大家要知道,过年回家多忙啊——帮忙家里做大扫除,看电影,看小说,高中同学聚餐,初中同学聚餐,小学同学聚餐,吃东西,睡觉,吃东西,睡觉,吃东西,睡觉……所以锻炼得抽着时间来。
但是,湫湫实在太忙了,所以没时间去算一天有多少时间可以用于锻炼,现在她把每日行程告诉你,拜托你帮忙算算吧~
皮埃斯:一天是24小时,每小时60分钟
Input
输入数据包括多组测试用例。
每组测试数据首先是一个整数n,表示当天有n件事要做。
接下来n行,第i行是第i件事的开始时间和结束时间,时间格式为HH:MM。
[Technical Specification]
1. 1 <= n <= 500000
2. 00 <= HH <= 23
3. 00 <= MM <= 59
每组测试数据首先是一个整数n,表示当天有n件事要做。
接下来n行,第i行是第i件事的开始时间和结束时间,时间格式为HH:MM。
[Technical Specification]
1. 1 <= n <= 500000
2. 00 <= HH <= 23
3. 00 <= MM <= 59
Output
请输出一个整数,即湫湫当天可以用于锻炼的时间(单位分钟)
Sample Input
1 15:36 18:40 4 01:35 10:36 04:54 22:36 10:18 18:40 11:47 17:53
Sample Output
1256 179Hint大量输入,建议用scanf读数据。
Source
2013腾讯编程马拉松初赛第一场(3月21日)
模拟上述过程,需要注意的时事件的时间可能出现重叠,对重叠部分合并即可。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;
struct Begin
{
int h;
int m;
Begin(int hh,int mm):
h(hh),m(mm)
{ }
};
bool operator<(const Begin &b,const Begin & c)
{
if(b.h<c.h)
return true;
if(b.h>c.h)
return false;
if(b.m<c.m)
return true;
return false;
}
bool operator==(const Begin &b,const Begin & c)
{
return (b.h==c.h)&&(b.m==c.m);
}
bool operator<(const pair<Begin,Begin> &pa,const pair<Begin,Begin> &pb)
{
return pa.first<pb.first?true:false;
}
const int SUM = 24*60;
vector< pair<Begin,Begin> > ths;
vector< pair<Begin,Begin> > s;///排序后的事情
int n=0;
inline int du(int sh, int sm, int eh, int em)
{///计算从[start,ends]内的时间
return (eh-sh)*60+(em-sm);
}
/**合并原始事件**/
void mer()
{
sort(ths.begin(),ths.end());
///使用贪心算法合并事情
int len = ths.size();
int newt=false;
Begin start=ths[0].first;
Begin endt =ths[0].second;
for(int i=1; i<len; ++i)
{
if(newt)
{
pair<Begin, Begin> p(start,endt);
s.push_back(p);
start = ths[i].first;///开始时间
endt = ths[i].second;///结束时间
newt = false;
continue;
}
if(ths[i].first<endt || ths[i].first==endt)///合并
{
endt = (endt<ths[i].second?ths[i].second:endt);
newt = false;
}
else
{///不合并,生成新事件
newt = true;
--i;
}
}
if(newt==false)///最后一个没加进去
{
pair<Begin, Begin> p(start,endt);
s.push_back(p);
}
}
/**从s中读取事情,然后返回空余时间*/
int foo()
{
int len = s.size();
int sumt=0;
for(int i=0; i<len; i++)
{
int sh,sm,eh,em;
sh = s[i].first.h;
sm = s[i].first.m;
eh = s[i].second.h;
em = s[i].second.m;
sumt += du(sh,sm,eh,em);
}
return SUM-sumt;
}
int main()
{
int sh,sm,eh,em;
while(scanf("%d",&n)!=EOF)
{
ths.clear();
s.clear();
for(int i=0; i<n; ++i)
{
scanf("%d:%d",&sh,&sm);
scanf("%d:%d",&eh,&em);
Begin b(sh,sm),c(eh,em);
pair<Begin, Begin> p(b,c);
ths.push_back(p);
}
mer();
printf("%d\n",foo());
}
return 0;
}
大量使用了vector和pair,还使用了stl的算法库里的sort函数。
运行结果为:
437MS | 2412K | 2560 B | G++ |
看到还有人用更简单的数组,不排序,直接算时间的:
#include <cstdio>
using namespace std;
int main()
{
int sh,sm,eh,em;
int t[24*60];
int n;
while(scanf("%d",&n)!=EOF)
{
for(int i=0; i<24*60;++i)
t[i]=0;
for(int i=0; i<n; ++i)
{
scanf("%d:%d",&sh,&sm);
scanf("%d:%d",&eh,&em);
int a1=sh*60+sm, a2=eh*60+em;
for(int i=a1; i<a2; ++i)
t[i] = 1;
}
int s=0;
for(int i=0; i<24*60; ++i)
if(t[i]==0)
s++;
printf("%d\n",s);
}
return 0;
}
后来用数组代替容器按照前一种方法重新实现了下,发现时间没变,1ms都没减少。
是不是可以断定,stl的实现效率已经非常高了,和数组几乎没什么明显的差别。