题干:

虽然制定了减肥食谱,但是湫湫显然克制不住吃货的本能,根本没有按照食谱行动! 

于是,结果显而易见… 


  但是没有什么能难倒高智商美女湫湫的,她决定另寻对策——吃没关系,咱吃进去再运动运动消耗掉不就好了? 


  湫湫在内心咆哮:“我真是天才啊~\(≧▽≦)/~” 



  可是,大家要知道,过年回家多忙啊——帮忙家里做大扫除,看电影,看小说,高中同学聚餐,初中同学聚餐,小学同学聚餐,吃东西,睡觉,吃东西,睡觉,吃东西,睡觉……所以锻炼得抽着时间来。 



  但是,湫湫实在太忙了,所以没时间去算一天有多少时间可以用于锻炼,现在她把每日行程告诉你,拜托你帮忙算算吧~ 



  皮埃斯:一天是24小时,每小时60分钟

Input输入数据包括多组测试用例。 


每组测试数据首先是一个整数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:53Sample Output 1256 179


解题报告:

    水题,包含一个合并区间的小模板,或者用开一个数组标记每个分钟是否有安排。后者比较好想但是用时稍长。


ac代码:(合并区间)

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;

struct Node {
int s,e;

} node[500000 + 5],nn[500000 + 5];

bool cmp(Node a,Node b) {
return a.s<b.s;

}
int main()
{
int n;
int cnt,maxx,minn;//
int hour,minutes;
int sum;
while(~scanf("%d",&n) ) {
sum=0;cnt=0;maxx=0;
for(int i = 0 ; i<n; i++) {
scanf("%d:%d",&hour,&minutes);
node[i].s=hour*60+minutes;
scanf("%d:%d",&hour,&minutes);
node[i].e=hour*60+minutes;
}
sort(node,node+n,cmp);
maxx=node[0].e;
nn[cnt].s=node[0].s;nn[cnt].e=maxx;
for(int i = 0; i<n; i++) {
if(node[i].s > maxx) {
nn[cnt++].e=maxx;//把maxx放入,并cnt++
nn[cnt].s=node[i].s;//把当前的start放入
maxx=node[i].e;nn[cnt].e=maxx;//为了防止i=n-1的情况(即读到最后一个node了),因为此时可能maxx可能还未更新到nn.e中
}

if(node[i].e>maxx) {
maxx=node[i].e;nn[cnt].e=maxx;
}

}
for(int i = 0; i<=cnt; i++) {
sum+=nn[i].e-nn[i].s;
}
printf("%d\n",24*60-sum);
}

return 0 ;
}


ac代码2:(标记法)

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
int main()
{
int t;
while(~scanf("%d",&t)) {
int ans[2000];
memset(ans, 0, sizeof(ans));
for(int i = 0; i < t; i++) {
int a, b, a1, b1;
scanf("%d:%d", &a, &b);
scanf("%d:%d", &a1, &b1);
for(int j = a * 60 + b; j < a1 * 60 + b1; j++)
ans[j] = 1;
}
int cnt= 0;
for(int i = 0; i < 1440; i++) {
if(!ans[i])
cnt++;
}
printf("%d\n",cnt);
}
return 0;

}

更:

ac代码3:(好像还可以用线段树?贴的代码)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <string>
#define INF 1000000
#define eps 1e-8
#define MAXN (2000+10)
#define MAXM (100000+10)
#define Ri(a) scanf("%d", &a)
#define Rl(a) scanf("%lld", &a)
#define Rf(a) scanf("%lf", &a)
#define Rs(a) scanf("%s", a)
#define Pi(a) printf("%d\n", (a))
#define Pf(a) printf("%.2lf\n", (a))
#define Pl(a) printf("%lld\n", (a))
#define Ps(a) printf("%s\n", (a))
#define W(a) while((a)--)
#define CLR(a, b) memset(a, (b), sizeof(a))
#define MOD 1000000007
#define LL long long
#define lson o<<1, l, mid
#define rson o<<1|1, mid+1, r
#define ll o<<1
#define rr o<<1|1
#define PI acos(-1.0)
#pragma comment(linker, "/STACK:102400000,102400000")
#define fi first
#define se second
using namespace std;
typedef pair<int, int> pii;
struct Tree{
int l, r, sum, lazy;
};
Tree tree[MAXN<<2];
void PushUp(int o){
tree[o].sum = tree[ll].sum + tree[rr].sum;
}
void PushDown(int o)
{
if(tree[o].lazy != -1)
{
tree[ll].lazy = tree[rr].lazy = tree[o].lazy;
tree[ll].sum = 0;
tree[rr].sum = 0;
tree[o].lazy = -1;
}
}
void Build(int o, int l, int r)
{
tree[o].l = l; tree[o].r = r;
tree[o].sum = r - l + 1; tree[o].lazy = -1;
if(l == r) return ;
int mid = (l + r) >> 1;
Build(lson); Build(rson);
}
void Update(int o, int L, int R)
{
if(tree[o].l == L && tree[o].r == R)
{
tree[o].lazy = 0;
tree[o].sum = 0;
return ;
}
PushDown(o);
int mid = (tree[o].l + tree[o].r) >> 1;
if(R <= mid) Update(ll, L, R);
else if(L > mid) Update(rr, L, R);
else {Update(ll, L, mid); Update(rr, mid+1, R);}
PushUp(o);
}
int main()
{
int n;
while(Ri(n) != EOF)
{
Build(1, 0, 1440-1);
for(int i = 0; i < n; i++)
{
int sh, sm, th, tm;
scanf("%d:%d%d:%d", &sh, &sm, &th, &tm);
int s = sh * 60 + sm;
int t = th * 60 + tm - 1;
if(s <= t) Update(1, s, t);
}
Pi(tree[1].sum);
}
return 0;
}

再附一个合并区间的错误代码:(感谢cxsys大佬发现的这个问题点,帮助更好的理解区间合并与贪心问题。)

他写的:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<stdlib.h>
using namespace std;

struct node{
int start_hour,start_mint,end_hour,end_mint;
};
bool cmp(node a,node b)
{
if(a.start_hour==b.start_hour)
return a.start_mint<b.start_mint;
return a.start_hour<b.start_hour;
}
struct node t[500005];
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
memset(t,0,sizeof(t));
int sum=0;
for(int i=0;i<n;i++)
{
scanf("%d:%d%d:%d",&t[i].start_hour,&t[i].start_mint,&t[i].end_hour,&t[i].end_mint);
}
sort(t,t+n,cmp);
for(int i=0;i<n;i++)
{
if(sum==0)
sum=(t[i].end_hour-t[i].start_hour)*60+(t[i].end_mint-t[i].start_mint);
if(t[i+1].start_hour*60+t[i+1].start_mint>t[i].end_hour*60+t[i].end_mint)
sum=sum+(t[i+1].end_hour-t[i+1].start_hour)*60+(t[i+1].end_mint-t[i+1].start_mint);
if(t[i+1].end_hour*60+t[i+1].end_mint>t[i].end_hour*60+t[i].end_mint)
sum=sum+(t[i+1].end_hour-t[i].end_hour)*60+(t[i+1].end_mint-t[i].end_mint);
if(t[i+1].end_hour*60+t[i+1].end_mint<t[i].end_hour*60+t[i].end_mint)
continue;
}
printf("%d\n",1440-sum);
}
return 0;
}

有点丑陋,不易阅读,我给他修改了下以后的代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<stdlib.h>
using namespace std;

struct node{
int start_hour,start_mint,end_hour,end_mint;
int s,e;
};
bool cmp(node a,node b)
{
if(a.start_hour==b.start_hour)
return a.start_mint<b.start_mint;
return a.start_hour<b.start_hour;
}
struct node t[500005];
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
memset(t,0,sizeof(t));
int sum=0;
for(int i=0;i<n;i++)
{
scanf("%d:%d%d:%d",&t[i].start_hour,&t[i].start_mint,&t[i].end_hour,&t[i].end_mint);
t[i].s=t[i].start_hour*60+t[i].start_mint;
t[i].e=t[i].end_hour*60+t[i].end_mint;
}
sort(t,t+n,cmp);
for(int i=0;i<n;i++)
{
if(sum==0)
sum=t[i].e-t[i].s;
if(t[i+1].s>=t[i].e)
sum=sum+t[i+1].e-t[i+1].s;
if(t[i+1].e>=t[i].e)
sum=sum+(t[i+1].e-t[i].e;
if(t[i+1].e<t[i].e)
continue;
}
printf("%d\n",1440-sum);
}
return 0;
}

比如一个例子:

【HDU - 4509】湫湫系列故事——减肥记II(合并区间模板 or 离散化标记 or 线段树)_i++

这么算应该是4+0+0.5小时,但其实是4小时


总结:合并区间的模板可否在优化一下?