怎样更有力气

来源:互联网 发布:linux oracle 服务状态 编辑:程序博客网 时间:2024/04/28 13:06

题目描述

OI大师抖儿在夺得银牌之后,顺利保送pku。这一天,抖儿问长者:“我虽然已经保送了,但我的志向是为国家健康工作五十年。请问我应该怎样变得更有力气?
  长者回答:“你啊,Too Young Too Simple,Sometimes Naive!如果你想要我教你,你要先进行艰苦的修行。
长者的住宅中有一堵长度为n的墙每天抖儿起床修行,会选择一段长度为x的区间染成白色。长者的住宅附近有一群香港记者,为了借助抖儿拜访长者,第i天香港记者会将区间[li,ri]染成白色来讨好抖儿(也就是说,每天墙会被抖儿和香港记者各染一次)。现在抖儿已经预先知道了香港记者的动向,他想知道他最少几天就能把墙全部染白,完成修行。

输入

第一行三个整数n,m,x,分别表示墙的长度,天数和区间的长度。
接下来m行,每行两个整数li、ri,表示香港记者在第i天会将区间[li,ri]染成白色。

输出

一行一个整数,表示抖儿最少几天能把墙全部染白。
如果m天之后依然无法染白,则输出“Poor Douer!”

样例输入

10 3 3
2 5
4 8
9 10

样例输出

2

HINT

【样例说明】

第一天抖儿刷墙的区间为[1,3]

第二天抖儿刷墙的区间为[8,10]


明显的二分答案,判断时候要求序列有序,个人认为我的方法更优些,别人写的是重新快排一遍,这样会再多一个log,其实只要一开始排一个序,后面只要O(n)的时间就可以了,很好想,记下原来的id,接下来就是判断,考试的时候判断死活调不出,导致大样例小了2qwq怎么办!
就是处理相邻之间的吗?不是!注意全体覆盖以及抖儿自己染的时候可能把后面一部分也给染了,然而这些我在考试时也注意到了啊qwq,真是奇了葩了。只好重新打一遍,简洁了点,写个题解吐槽吐槽!!!大哭
嗯longlong注意一下哈。


#include <cstdio>#include <iostream>#include <algorithm>#include <cstring>#include <cmath>#define ll long long#define M 100000+1000using namespace std;ll n,x;int m,q[M];struct node{ll l,r;int id;}a[M];bool cmp(node a,node b){return a.l<b.l || a.l==b.l && a.r<b.r;}int check(int mid){ll ans=0,pre=0;int num=0;for(int i=1;i<=m;i++) if(a[i].id<=mid) q[++num]=i;q[++num]=m+1;for(int i=1;i<=mid+1;i++){if(a[q[i]].l>pre+1){if(!x) return 0;ll tmp=(a[q[i]].l-pre-2)/x+1;if(pre+tmp*x>a[q[i]].r) pre=pre+tmp*x;ans+=tmp;if(ans>mid) return 0;}if(a[q[i]].r>pre) pre=a[q[i]].r;}return 1;}int main(){scanf("%lld%d%lld",&n,&m,&x);for(int i=1;i<=m;i++){scanf("%lld%lld",&a[i].l,&a[i].r);a[i].id=i;}sort(a+1,a+1+m,cmp);a[m+1].l=n+1;int l=1,r=m;bool flag=false;while(l<r){int mid=(l+r)>>1;if(check(mid)){r=mid;flag=true;}else l=mid+1;}if (!flag) puts("Poor Douer!");else printf("%d\n",r);return 0;}




原创粉丝点击