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

题干:

虽然制定了减肥食谱,但是湫湫显然克制不住吃货的本能,根本没有按照食谱行动! 
于是,结果显而易见… 
  但是没有什么能难倒高智商美女湫湫的,她决定另寻对策——吃没关系,咱吃进去再运动运动消耗掉不就好了? 
  湫湫在内心咆哮:“我真是天才啊~\(≧▽≦)/~” 

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

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

  皮埃斯:一天是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:53
Sample 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小时


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


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/442137.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

layui中日期格式化方式

如何对日期进行格式化 layui.util.toDateString(日期值, yyyy-MM-dd HH:mm:ss.fff)

【51NOD - 1523】 非回文(dfs)

题干&#xff1a;一个字符串是非回文的&#xff0c;当且仅当&#xff0c;他只由前p个小写字母构成&#xff0c;而且他不包含长度大于等于2的回文子串。 给出长度为n的非回文串s。请找出字典序比s大的&#xff0c;而且字典序要最小的长度为n的非回文。 Input单组测试数据。 第一…

C# XML字符串与DataTable相互转换

不多说&#xff0c;直接上代码&#xff1a; //DataTable转Xml字符串 public static string ConvertDataTableToXML(DataTable xmlDS){MemoryStream stream null;XmlTextWriter writer null;try{stream new MemoryStream();writer new XmlTextWriter(stream, Encoding.Defa…

【HDU - 2093】 考试排名(排序+格式输出)

题干&#xff1a;C编程考试使用的实时提交系统&#xff0c;具有即时获得成绩排名的特点。它的功能是怎么实现的呢&#xff1f; 我们做好了题目的解答&#xff0c;提交之后&#xff0c;要么“AC”&#xff0c;要么错误&#xff0c;不管怎样错法&#xff0c;总是给你记上一笔&…

C# 实现将网络资源保存到本地

/// <summary>/// 单个文件保存从对方服务器到自己网站/// </summary>/// <param name"aUrl"></param>/// <param name"aPath"></param>/// <returns></returns>[HttpGet]public string FileSave(string …

【sdut 1751】 区间覆盖问题

区间覆盖问题Time Limit: 1000 ms Memory Limit: 65536 KiB Submit Statistic Discuss Problem Description设x1 , x2 ,…… , xn 是实直线上的n 个点。用固定长度的闭区间覆盖这n 个点&#xff0c;至少需要多少个这样的固定长度闭区间?对于给定的实直线上的n个点和闭区间的长…

C# 读取根目录的json文件中的某个值

/// <summary>/// 读取JSON文件/// </summary>/// <param name"key">JSON文件中的key值</param>/// <returns>JSON文件中的value值</returns>public string Readjson(string key){//获取winform应用根目录string jsonfile Appl…

【nyoj 47】 过河问题(思维)

过河问题时间限制&#xff1a;1000 ms | 内存限制&#xff1a;65535 KB难度&#xff1a;5描述在漆黑的夜里&#xff0c;N位旅行者来到了一座狭窄而且没有护栏的桥边。如果不借助手电筒的话&#xff0c;大家是无论如何也不敢过桥去的。不幸的是&#xff0c;N个人一共只带了一只…

layui数据表格循环数据给特殊行变颜色遇到的bug

数据表格加载玩数据后&#xff0c;进行颜色区分&#xff0c;然后再进行排序&#xff0c;发现颜色变化有bug 原因&#xff1a; //其中res.data数据并没有变化&#xff0c;只是渲染数据顺序发生了变化&#xff0c;这时候&#xff0c;如此循环便会出现问题 $.each(res.data, fun…

贪心策略--16经典问题总结!

贪心算法编号题目1货郎担问题&#xff1a;货郎担问题&#xff1a;假定有五个城市&#xff0c;已知费用矩阵如下&#xff0c;分别从五个城市出发&#xff0c;然后选取一条费用最小的线路&#xff0c;验证这种算法不能得到最优解。贪心选择&#xff1a;每次选择之前没有走过的费用…

网站前端组织冒泡事件

判断event.stopPropagation();是否可行&#xff0c;不行再使用window.event.cancelBubble true;

【nyist】6 喷水装置(一) (简单的贪心)

喷水装置&#xff08;一&#xff09;时间限制&#xff1a;3000 ms | 内存限制&#xff1a;65535 KB难度&#xff1a;3描述现有一块草坪&#xff0c;长为20米&#xff0c;宽为2米&#xff0c;要在横中心线上放置半径为Ri的喷水装置&#xff0c;每个喷水装置的效果都会让以它为…

layui数据表格获取当前页数

$(".layui-laypage-em").next().html()

最大素因子(不是题目!自己写着玩的。。。)

话不多说直接上代码&#xff1a; #include<iostream> #include<cstring> using namespace std; int res[10000]; int cnt; long long su[100000000]; bool isprime[200000000]; void prime() {memset(isprime,1,sizeof(isprime));cnt1;isprime[0]isprime[1]0;for(i…

.net core 5 IIS Api网站部署需要注意(同.net 6)

应用程序池&#xff1a;.net clr 版本&#xff1a;无托管代码 2.安装.NET Core SDK和AspNetCoreModule托管模块 此工具要在官网直接下载即可

【HDU - 2087】 剪花布条(直接模拟 or KMP)

题干&#xff1a; 一块花布条&#xff0c;里面有些图案&#xff0c;另有一块直接可用的小饰条&#xff0c;里面也有一些图案。对于给定的花布条和小饰条&#xff0c;计算一下能从花布条中尽可能剪出几块小饰条来呢&#xff1f; Input输入中含有一些数据&#xff0c;分别是成…

从客户端*****中检测到有潜在危险的 Request.Form 值。

MVC前端调用后台控制器方法报错 解决方案&#xff1a; //在控制器方法前添加以下修饰 [ValidateInput(false)]

【九度oj 1135】【OpenJ_Bailian - 2915】 字符串排序 (水)

题干&#xff1a; 先输入你要输入的字符串的个数。然后换行输入该组字符串。每个字符串以回车结束&#xff0c;每个字符串少于一百个字符。如果在输入过程中输入的一个字符串为“stop”&#xff0c;也结束输入。 然后将这输入的该组字符串按每个字符串的长度&#xff0c;由小到…

webapi自宿主设置本地端口使用https协议

首先&#xff0c;你要申请证书&#xff0c;然后导入到证书里面&#xff1a; 具体步骤&#xff1a;运行–MMC命令&#xff0c;进入如下界面进行设置&#xff1a; 一直点下一步直到完成&#xff0c;然后将证书导入到个人里面 这个时候进入cmd程序运行如下命令&#xff1a; /…

C# linq Expression left join如何使用

eg&#xff1a; 注意&#xff1a;on 前后要保持字段名一致 var bleftQuery from f in bFamiliesjoin a in bAudits on new{Idf.Id,DCYIdf.ModifyID} equals new{Ida.HealthFamilyId,a.DCYId} into nafrom a in na.DefaultIfEmpty()select new FamilyWithAudit(){Id f.Id,Sea…