【问题描述】
本题中,我们将用符号 LcJ 表示对 c 向下取整,例如: L3.0J = L3.1J = L3.9J = 3。 蛐蛐国最近蚯蚓成灾了!隔壁跳蚤国的跳蚤也拿蚯蚓们没办法,蛐蛐国王只好去请神刀手来帮他们消灭蚯蚓。 蛐蛐国里现在共有 n 只蚯蚓( n 为正整数)。每只蚯蚓拥有长度,我们设第 i 只蚯蚓的长度为 ai ( i = 1, 2, . . . , n ),并保证所有的长度都是非负整数(即:可能存在长度为0的蚯蚓)。
蛐蛐国王当然知道怎么做啦! 但是他想考考你……
【输入格式】
从文件 earthworm.in 中读入数据。
第一行包含六个整数 n, m, q, u, v, t ,其中: n, m, q 的意义见【问题描述】; u, v, t 均 为正整数;你需要自己计算 p = u/v (保证 0 < u < v );t 是输出参数,其含义将会在【输出格式】中解释。
第二行包含 n 个非负整数,为 a1, a2, . . . , an ,即初始时 n 只蚯蚓的长度。 同一行中相邻的两个数之间,恰好用一个空格隔开。 保证 1 ≤ n ≤ 105 , 0 ≤ m ≤ 7 × 106 , 0 < u < v ≤ 109 , 0 ≤ q ≤ 200 , 1 ≤ t ≤ 71 , 0 ≤ ai ≤ 108 。
【输出格式】
输出到文件 earthworm.out 第一行输出 个整数,按时间顺序,依次输出第 t秒,第 2t 秒,第 3t 秒,......被切 断蚯蚓(在被切断前)的长度。第二行输出个整数,输出 m 秒后蚯蚓的长度:需要按从大到小的顺序,依次输出排名第 t ,第 2t ,第 3t ,. . . . . . 的长度。 同一行中相邻的两个数之间,恰好用一个空格隔开。即使某一行没有任何数需要输出,你也应输出一个空行。 请阅读样例来更好地理解这个格式。
题解
我们构建3个单调队列,分别记为q[0],q[1],q[2]。其中q[0]记录初始时每条蚯蚓的长度,并将其按从大到小的顺序排列。q[1]记录每次切割后长的那一截的长度。q[2]记录每次切割后短的那一截的长度。对于蚯蚓增长的长度,我们可以运用标记的思想,因为每条蚯蚓所增长的长度都是一样的。
显然,这样子构出来的3个队列都是单调递减的,于是每次切割,取3个队列队首最大的元素进行切割,假设它的大小为x,当前增长长度为l,每单位时间蚯蚓长度增长L。那么,这条蚯蚓的长度len=x+l,切割后长度记为l1和l2,那么放入队列时将l1和l2都减去L+l,这样它们就可以和整个队列中的元素的标记同步了。
需要输出的时候判断一下当前的时间是否是t的倍数即可。
代码
type
arr=array [1..3] of longint;
var
gg:boolean;
n,m,q,u,v,tn:longint;
l,r:arr;
a:array [1..3,0..10000001] of int64;
procedure qsort(l,r:longint);
var
i,j:longint;
mid,t:int64;
begin
if l>r then exit;
i:=l; j:=r;
mid:=a[1,(i+j) div 2];
repeat
while a[1,i]>mid do inc(i);
while a[1,j]<mid do dec(j);
if i<=j then
begin
t:=a[1,i]; a[1,i]:=a[1,j]; a[1,j]:=t;
t:=a[2,i]; a[2,i]:=a[2,j]; a[2,j]:=t;
t:=a[3,i]; a[3,i]:=a[3,j]; a[3,j]:=t;
inc(i); dec(j);
end;
until i>j;
qsort(l,j);
qsort(i,r);
end;
procedure init;
var
i:longint;
begin
readln(n,m,q,u,v,tn);
for i:=1 to n+m do
begin
a[1,i]:=-maxlongint;
a[2,i]:=-maxlongint;
a[3,i]:=-maxlongint;
end;
for i:=1 to n do
read(a[1,i]);
qsort(1,n); gg:=false;
end;
procedure main;
var
i,j,k:longint;
max,x,y,tk,t:int64;
begin
l[1]:=1; r[1]:=n;
l[2]:=1; r[2]:=0;
l[3]:=1; r[3]:=0;
for i:=1 to m do
begin
max:=-maxlongint;
for j:=1 to 3 do
if a[j,l[j]]>max then
begin
max:=a[j,l[j]];
k:=j;
end;
t:=max+(i-1)*q;
inc(l[k]);
if i mod tn=0 then
begin
write(t,' ');
end;
x:=trunc(t*u/v); y:=trunc(t-x);
if x<y then
begin
tk:=x; x:=y; y:=tk;
end;
inc(r[2]); a[2,r[2]]:=x-i*q;
inc(r[3]); a[3,r[3]]:=y-i*q;
end;
writeln;
end;
procedure print;
var
i,j,k:longint;
max,t:int64;
begin
for i:=1 to n+m do
begin
max:=-maxlongint;
for j:=1 to 3 do
if a[j,l[j]]>max then
begin
max:=a[j,l[j]];
k:=j;
end;
t:=max+m*q;
inc(l[k]);
if i mod tn=0 then write(t,' ');
end;
end;
begin
init;
main;
print;
end.