(NOIP2015)复赛模拟试题 vijos1165 火烧赤壁

来源:互联网 发布:图像分割算法后处理 编辑:程序博客网 时间:2024/04/27 12:12

描述

曹操平定北方以后,公元208年,率领大军南下,进攻刘表。他的人马还没有到荆州,刘表已经病死。他的儿子刘琮听到曹军声势浩大,吓破了胆,先派人求降了。

孙权任命周瑜为都督,拨给他三万水军,叫他同刘备协力抵抗曹操。

隆冬的十一月,天气突然回暖,刮起了东南风。

没想到东吴船队离开北岸大约二里距离,前面十条大船突然同时起火。火借风势,风助火威。十条火船,好比十条火龙一样,闯进曹军水寨。那里的船舰,都挤在一起,又躲不开,很快地都烧起来。一眨眼工夫,已经烧成一片火海。

曹操气急败坏的把你找来,要你钻入火海把连环线上着火的船只的长度统计出来!

格式

输入格式

第一行:N
以后N行,每行两个数:Ai Bi(表示连环线上着火船只的起始位置和终点,-10^9<=Ai,Bi<=10^9)

输出格式

输出着火船只的总长度

样例1

样例输入1[复制]

3-1 15 112 9

样例输出1[复制]

11

提示

n<=20000
如果Ai=Bi是一个点则看作没有长度

 

分析:

设船头坐标为s[i],船尾坐标e[i]
先按船头升序排列(显然用快排),再从第一艘考虑到最后一艘,若遇到重叠的船则处理
只有两种重叠情况:
1、后一艘船的船头坐标<前一艘船的船尾坐标并且后一艘船的船尾坐标>=前一艘船的船尾坐标,即s<e[i]且e>=e[i]:
那么只要将前一艘船的船尾坐标改为后一艘船的船头坐标即可,即e[i]:=s
2、后一艘船的船尾坐标<=前一艘船的船尾坐标,即e<=e[i]:
那么只要先将后一艘船的船尾坐标改为前一艘船的船尾坐标,再将前一艘船的船尾坐标改为后一艘船的船头坐标即可,即e:=e[i];e[i]:=s;
全部处理一遍后就可保证所有船只无重叠,最后对(e[i]-s[i])求和就AC了。

标程:

var
 l,r:array[1..20000]of longint;
 n,i,a,b:longint;  ans:int64;
procedure q(i,j:longint);var mid,ll,rr,p:longint;
begin
 ll:=i;rr:=j;mid:=l[(i+j)>>1];
 repeat
  while l[ll]<mid do inc(ll);
  while l[rr]>mid do dec(rr);
  if ll<=rr then begin p:=l[ll];l[ll]:=l[rr];l[rr]:=p;p:=r[ll];r[ll]:=r[rr];r[rr]:=p;inc(ll);dec(rr);end;
 until ll>rr;
 if ll<j then q(ll,j);
 if rr>i then q(i,rr);
end;
begin
 assign(input,'fire.in');assign(output,'fire.out');
 reset(input);rewrite(output);
 read(n);
 for i:=1 to n do read(l[i],r[i]);
 q(1,n);
 a:=l[1];b:=r[1];
 for i:=1 to n do
  begin
   if (l[i]<=b)and(r[i]>b) then b:=r[i];
   if l[i]>b then begin ans:=ans+b-a;b:=r[i];a:=l[i];end;
  end;
  ans:=ans+b-a;
 writeln(ans);
 close(input);close(output);
end.

 

0 0
原创粉丝点击