题干:
虽然制定了减肥食谱,但是湫湫显然克制不住吃货的本能,根本没有按照食谱行动!
于是,结果显而易见…
但是没有什么能难倒高智商美女湫湫的,她决定另寻对策——吃没关系,咱吃进去再运动运动消耗掉不就好了?
湫湫在内心咆哮:“我真是天才啊~\(≧▽≦)/~”
可是,大家要知道,过年回家多忙啊——帮忙家里做大扫除,看电影,看小说,高中同学聚餐,初中同学聚餐,小学同学聚餐,吃东西,睡觉,吃东西,睡觉,吃东西,睡觉……所以锻炼得抽着时间来。
但是,湫湫实在太忙了,所以没时间去算一天有多少时间可以用于锻炼,现在她把每日行程告诉你,拜托你帮忙算算吧~
皮埃斯:一天是24小时,每小时60分钟
Input输入数据包括多组测试用例。
于是,结果显而易见…
但是没有什么能难倒高智商美女湫湫的,她决定另寻对策——吃没关系,咱吃进去再运动运动消耗掉不就好了?
湫湫在内心咆哮:“我真是天才啊~\(≧▽≦)/~”
可是,大家要知道,过年回家多忙啊——帮忙家里做大扫除,看电影,看小说,高中同学聚餐,初中同学聚餐,小学同学聚餐,吃东西,睡觉,吃东西,睡觉,吃东西,睡觉……所以锻炼得抽着时间来。
但是,湫湫实在太忙了,所以没时间去算一天有多少时间可以用于锻炼,现在她把每日行程告诉你,拜托你帮忙算算吧~
皮埃斯:一天是24小时,每小时60分钟
每组测试数据首先是一个整数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;
}
比如一个例子:
这么算应该是4+0+0.5小时,但其实是4小时
总结:合并区间的模板可否在优化一下?