怎样更有力气

A: 怎样更有力气

时间限制: 2 Sec   内存限制: 128 MB
提交: 96   解决: 12
[ 提交][ 状态][ 讨论版]

题目描述

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

输入

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

输出

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

样例输入

10 3 32 54 89 10

样例输出

2

提示

【样例说明】

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

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

【限制与约定】


测试点编号

n

m

x

1

n≤10

m≤1

 

2

n≤10

m≤10

3

n≤100

m≤100

4

n≤1000

m≤1000

5

n≤10000

m≤10000

6

n≤100000

 

 

m≤100000

 

x=0

7

n≤10 18

8

n≤100000

 

9

n≤10 18

10

对于所有的数据,保证 n≤10 18 ,m≤100000,x≤n且数据随机

【后记】

在你的帮助下,抖儿完成修行的时间是原来的0.01倍。

抖儿对长者说:“我明白了!只有每天坚持锻炼,才能获得力量。”

长者嘿嘿一笑:“你想多了。我只是想让你刷墙而已。”

说完,长者一溜烟地跑了,速度比香港记者还要快 好几倍

1、当m=1时比较简单。

2、n,m≤10^4
考虑第i天,先处理香港记者染白的区间。
令dp[i]表示1~i全染白至少操作几次。
则dp[i]=dp[i-1](i为白点)或dp[i-x]+1(i为黑点)
时间复杂度O(nm)
3、x=0
二分答案,那么只要看香港记者染白的区间是否将墙完全覆盖即可。
将区间按左端点排序,比较区间的左端点与前一个区间的右端点即可。
4、正解
其实已经很明了了。
在3中,如果当前区间的左端点小于上一个区间的右端点,就直接退出。
现在只要从上一个区间的右端点+1开始凃,一直涂到≥当前区间左端点即可。
注意到一次可能直接把整一段覆盖了,那么下一次就要从当前涂到的地方开始。
Code:
var
  l1,r1,l,r:array[1..100000] of int64;
  m,i,tt:longint;n,x:int64;
procedure sort(a,b:longint);
var i,j,x,y,p:longint;
begin
  i:=a;j:=b;
  x:=l1[(a+b) div 2];p:=r1[(a+b) div 2];
  repeat
    while (l1[i]<x)or((l1[i]=x)and(r1[i]<p)) do inc(i);
    while (l1[j]>x)or((l1[j]=x)and(r1[j]>p)) do dec(j);
    if not(i>j) then
    begin
      y:=l1[i];l1[i]:=l1[j];l1[j]:=y;
      y:=r1[i];r1[i]:=r1[j];r1[j]:=y;
      inc(i);dec(j);
    end;
  until i>j;
  if a<j then sort(a,j);
  if i<b then sort(i,b);
end;
function max(a,b:longint):longint;
begin
  if a>b then exit(a) else exit(b);
end;
function right(k:longint):boolean;
var i,tt:longint;ans:int64;
begin
  for i:=1 to k do
  begin
    l1[i]:=l[i];
    r1[i]:=r[i];
  end;
  sort(1,k);
  ans:=0;
  if (x=0)and(l1[1]>1) then exit(false) else
  begin
    if l1[1]>1 then
    begin
      if ((l1[1]-1) mod x=0) then ans:=ans+(l1[1]-1) div x else
        ans:=ans+(l1[1]-1) div x+1;
      r1[1]:=max(x,r1[1]);
    end;
    for i:=2 to k do
    begin
      if l1[i]<=r1[i-1]+1 then
      begin
        r1[i]:=max(r1[i],r1[i-1]);
        continue;
      end;
      if (x=0) then exit(false) else
      begin
        if ((l1[i]-r1[i-1]-1) mod x=0) then
          tt:=((l1[i]-r1[i-1]-1) div x) else
          tt:=(l1[i]-r1[i-1]-1) div x+1;
          ans:=ans+tt;
        r1[i]:=max(r1[i-1]+x*tt,r1[i]);
        r1[i]:=max(r1[i],r1[i-1])
      end;
      if ans>k then exit(false);
    end;
    if r1[k]<n then
    begin
      if x=0 then exit(false);
      if (n-r1[k]) mod x=0 then
        ans:=ans+(n-r1[k]) div x else
        ans:=ans+(n-r1[k]) div x+1;
    end;
  end;
  if ans>k then exit(false) else exit(true);
end;
function find(a,b:longint):longint;
var mid:longint;
begin
  if a=b then exit(a);
  mid:=(a+b) div 2;
  if right(mid) then
    find:=find(a,mid) else find:=find(mid+1,b);
end;
begin
  readln(n,m,x);
  for i:=1 to m do readln(l[i],r[i]);
  if not(right(m)) then writeln('Poor Douer!') else
  writeln(find(1,m));
end.

猜你喜欢

转载自blog.csdn.net/qq_34531807/article/details/77971128