1746. 【usaco 2013 feb Bronze】粉刷栅栏(Painting the Fence)
题目:
农夫约翰最近正在将他的栅栏粉刷一下(这里所有的栅栏都是在一条直线上的)。他是这样来粉刷的:他从位置0出发,然后执行N条指令,例如,指令可以是“10
L”,表示约翰从当前的位置向左移动10个单位的距离,并且粉刷移动过程中遇到的栅栏,又或者是“15 R”,表示约翰从当前的位置向右移动15个单位的距离,并且粉刷移动过程中遇到的栅栏。
给定所有约翰需要移动的指令,请计算所有栅栏中至少被粉刷两次的栅栏的总长度。约翰最多远离初始位置1000000000个单位的距离。
输入:
第一行一个正整数N。
接下来第2行到第N+1行,每行表示每条指令。
接下来第2行到第N+1行,每行表示每条指令。
输出:
只有一行一个整数,表示所有栅栏中至少被粉刷两次的栅栏的总长度。
数据范围:
1<=N<=100000。
这就是道水题啊!
我们将指令全部转化为区间
排个序(我怕被卡,打了个堆排)
然后按照usaco挤牛奶的方法做
每次将当前区间与上一个区间的交集累加进答案
然后更新当前区间
比赛时信心满满
20分钟码完
一看成绩(10分)
傻眼
赛后听讲,发现正解和我的方法完全一样
百思不得其解
先是检查了排序
又看数据范围
最后才发现少打了几个判断
改完,AC
标程:
var ch,kong:char;
a,d:array[0..100000,1..2]of longint;
n,i,x,j,k,l,s,m,ans,len,head,tail:longint;
bz:array[1..100000]of longint;
procedure up(t:longint);
var x,y:longint;
begin
x:=t;
while(x>1)and((d[x div 2,1]>d[x,1])or(d[x div 2,1]=d[x,1])and(d[x div 2,2]>d[x,2]))do
begin
y:=x div 2;
d[0]:=d[x];
d[x]:=d[y];
d[y]:=d[0];
x:=y;
end;
end;
procedure down(t:longint);
var x,y:longint;
begin
x:=t;
while((x*2<=len)and((d[x*2,1]<d[x,1])or(d[x*2,1]=d[x,1])and(d[x*2,2]<d[x,2])))or
((x*2+1<=len)and((d[x*2+1,1]<d[x,1])or(d[x*2+1,1]=d[x,1])and(d[x*2+1,2]<d[x,2])))do
begin
y:=x*2;
if(d[y+1,1]<d[y,1])or(d[y+1,1]=d[y,1])and(d[y+1,2]<d[y,2])then inc(y);
d[0]:=d[x];
d[x]:=d[y];
d[y]:=d[0];
x:=y;
end;
end;
procedure insert(t:longint);
begin
inc(len);
d[len]:=a[t];
up(len);
end;
procedure dsort;
begin
for i:=1 to n do
insert(i);
a[1]:=d[1];
for i:=2 to n do
begin
d[1]:=d[len];
dec(len);
down(1);
a[i]:=d[1];
end;
end;
function max(a,b:longint):longint;
begin if a>b then max:=a else max:=b; end;
begin
assign(input,'paint.in');
assign(output,'paint.out');
reset(input);
rewrite(output);
readln(n);
x:=0;
for i:=1 to n do
begin
readln(s,kong,ch);
if ch='R' then
begin
a[i,1]:=x;
a[i,2]:=x+s;
x:=x+s;
end;
if ch='L' then
begin
a[i,1]:=x-s;
a[i,2]:=x;
x:=x-s;
end;
end;
dsort;
head:=a[1,1];
tail:=a[1,2];
ans:=0;
for i:=2 to n do
begin
if a[i,2]<=head then continue;
if(a[i,2]<=tail)then
begin
ans:=ans+(a[i,2]-max(a[i,1],head));
head:=a[i,2]
end
else
if a[i,1]>=tail then
begin
head:=a[i,1];
tail:=a[i,2]
end
else
if a[i,1]<=head then
begin
ans:=ans+(tail-head);
head:=tail;
tail:=a[i,2]
end
else
begin
ans:=ans+(tail-a[i,1]);
head:=tail;
tail:=a[i,2];
end;
end;
writeln(ans);
close(input);
close(output);
end.
USACO栅栏粉刷问题解析

本文解析USACO 2013 February Bronze级别竞赛中的栅栏粉刷问题,介绍了如何通过转化指令为区间并进行排序,使用类似挤牛奶的方法计算至少被粉刷两次的栅栏总长度。
1388

被折叠的 条评论
为什么被折叠?



