题目描述
本题中,我们将用符号 ⌊ c ⌋ \lfloor c \rfloor ⌊c⌋ 表示对 c c c 向下取整,例如: ⌊ 3.0 ⌋ = ⌊ 3.1 ⌋ = ⌊ 3.9 ⌋ = 3 \lfloor 3.0 \rfloor = \lfloor 3.1 \rfloor = \lfloor 3.9 \rfloor = 3 ⌊3.0⌋=⌊3.1⌋=⌊3.9⌋=3。
蛐蛐国最近蚯蚓成灾了!隔壁跳蚤国的跳蚤也拿蚯蚓们没办法,蛐蛐国王只好去请神刀手来帮他们消灭蚯蚓。
蛐蛐国里现在共有 n n n 只蚯蚓( n n n 为正整数)。每只蚯蚓拥有长度,我们设第 i i i 只蚯蚓的长度为 a i a_i ai ( i = 1 , 2 , … , n i=1,2,\dots,n i=1,2,…,n),并保证所有的长度都是非负整数(即:可能存在长度为 0 0 0 的蚯蚓)。
每一秒,神刀手会在所有的蚯蚓中,准确地找到最长的那一只(如有多个则任选一个)将其切成两半。神刀手切开蚯蚓的位置由常数 p p p(是满足 0 < p < 1 0 < p < 1 0<p<1 的有理数)决定,设这只蚯蚓长度为 x x x,神刀手会将其切成两只长度分别为 ⌊ p x ⌋ \lfloor px \rfloor ⌊px⌋ 和 x − ⌊ p x ⌋ x - \lfloor px \rfloor x−⌊px⌋ 的蚯蚓。特殊地,如果这两个数的其中一个等于 0 0 0,则这个长度为 0 0 0 的蚯蚓也会被保留。此外,除了刚刚产生的两只新蚯蚓,其余蚯蚓的长度都会增加 q q q(是一个非负整常数)。
蛐蛐国王知道这样不是长久之计,因为蚯蚓不仅会越来越多,还会越来越长。蛐蛐国王决定求助于一位有着洪荒之力的神秘人物,但是救兵还需要 m m m 秒才能到来……( m m m 为非负整数)
蛐蛐国王希望知道这 m m m 秒内的战况。具体来说,他希望知道:
- m m m 秒内,每一秒被切断的蚯蚓被切断前的长度(有 m m m 个数);
- m m m 秒后,所有蚯蚓的长度(有 n + m n + m n+m 个数)。
蛐蛐国王当然知道怎么做啦!但是他想考考你……
输入格式
第一行包含六个整数 n , m , q , u , v , t n,m,q,u,v,t n,m,q,u,v,t,其中: n , m , q n,m,q n,m,q 的意义见【问题描述】; u , v , t u,v,t u,v,t 均为正整数;你需要自己计算 p = u / v p=u / v p=u/v(保证 0 < u < v 0 < u < v 0<u<v); t t t 是输出参数,其含义将会在【输出格式】中解释。
第二行包含 n n n 个非负整数,为 a 1 , a 2 , … , a n a_1, a_2, \dots, a_n a1,a2,…,an,即初始时 n n n 只蚯蚓的长度。
同一行中相邻的两个数之间,恰好用一个空格隔开。
保证 1 ≤ n ≤ 1 0 5 1 \leq n \leq 10^5 1≤n≤105, 0 ≤ m ≤ 7 × 1 0 6 0 \leq m \leq 7 \times 10^6 0≤m≤7×106, 0 < u < v ≤ 1 0 9 0 < u < v \leq 10^9 0<u<v≤109, 0 ≤ q ≤ 200 0 \leq q \leq 200 0≤q≤200, 1 ≤ t ≤ 71 1 \leq t \leq 71 1≤t≤71, 0 ≤ a i ≤ 1 0 8 0 \leq a_i \leq 10^8 0≤ai≤108。
输出格式
第一行输出 ⌊ m t ⌋ \left \lfloor \frac{m}{t} \right \rfloor ⌊tm⌋ 个整数,按时间顺序,依次输出第 t t t 秒,第 2 t 2t 2t 秒,第 3 t 3t 3t 秒,……被切断蚯蚓(在被切断前)的长度。
第二行输出 ⌊ n + m t ⌋ \left \lfloor \frac{n+m}{t} \right \rfloor ⌊tn+m⌋ 个整数,输出 m m m 秒后蚯蚓的长度;需要按从大到小的顺序,依次输出排名第 t t t,第 2 t 2t 2t,第 3 t 3t 3t,……的长度。
同一行中相邻的两个数之间,恰好用一个空格隔开。即使某一行没有任何数需要输出,你也应输出一个空行。
请阅读样例来更好地理解这个格式。
样例 #1
样例输入 #1
3 7 1 1 3 1
3 3 2
样例输出 #1
3 4 4 4 5 5 6
6 6 6 5 5 4 4 3 2 2
样例 #2
样例输入 #2
3 7 1 1 3 2
3 3 2
样例输出 #2
4 4 5
6 5 4 3 2
样例 #3
样例输入 #3
3 7 1 1 3 9
3 3 2
样例输出 #3
//空行
2
提示
【样例解释1】
在神刀手到来前: 3 3 3只蚯蚓的长度为 3 , 3 , 2 3,3,2 3,3,2。
1 1 1秒后:一只长度为 3 3 3的蚯蚓被切成了两只长度分别为 1 1 1和 2 2 2的蚯蚓,其余蚯蚓的长度增加了 1 1 1。最终 4 4 4只蚯蚓的长度分别为 ( 1 , 2 ) , 4 , 3 (1,2),4,3 (1,2),4,3。括号表示这个位置刚刚有一只蚯蚓被切断
2 2 2秒后:一只长度为 4 4 4的蚯蚓被切成了 1 1 1和 3 3 3。 5 5 5只蚯蚓的长度分别为: 2 , 3 , ( 1 , 3 ) , 4 2,3,(1,3),4 2,3,(1,3),4。
3秒后:一只长度为 4 4 4的蚯蚓被切断。 6 6 6只蚯蚓的长度分别为: 3 , 4 , 2 , 4 , ( 1 , 3 ) 3,4,2,4,(1,3) 3,4,2,4,(1,3)。
4 4 4秒后:一只长度为 4 4 4的蚯蚓被切断。 7 7 7只蚯蚓的长度分别为: 4 , ( 1 , 3 ) , 3 , 5 , 2 , 4 4,(1,3),3,5,2,4 4,(1,3),3,5,2,4。
5 5 5秒后:一只长度为 5 5 5的蚯蚓被切断。 8 8 8只蚯蚓的长度分别为: 5 , 2 , 4 , 4 , ( 1 , 4 ) , 3 , 5 5,2,4,4,(1,4),3,5 5,2,4,4,(1,4),3,5。
6 6 6秒后:一只长度为 5 5 5的蚯蚓被切断。 9 9 9只蚯蚓的长度分别为: ( 1 , 4 ) , 3 , 5 , 5 , 2 , 5 , 4 , 6 (1,4),3,5,5,2,5,4,6 (1,4),3,5,5,2,5,4,6。
7 7 7秒后:一只长度为 6 6 6的蚯蚓被切断。 10 10 10只蚯蚓的长度分别为: 2 , 5 , 4 , 6 , 6 , 3 , 6 , 5 , ( 2 , 4 ) 2,5,4,6,6,3,6,5,(2,4) 2,5,4,6,6,3,6,5,(2,4)。所以, 7 7 7秒内被切断的蚯蚓的长度依次为 3 , 4 , 4 , 4 , 5 , 5 , 6 3,4,4,4,5,5,6 3,4,4,4,5,5,6。 7 7 7秒后,所有蚯蚓长度从大到小排序为 6 , 6 , 6 , 5 , 5 , 4 , 4 , 3 , 2 , 2 6,6,6,5,5,4,4,3,2,2 6,6,6,5,5,4,4,3,2,2
【样例解释2】
这个数据中只有 t = 2 t=2 t=2与上个数据不同。只需在每行都改为每两个数输出一个数即可。
虽然第一行最后有一个 6 6 6没有被输出,但是第二行仍然要重新从第二个数再开始输出。
【样例解释3】
这个数据中只有 t = 9 t=9 t=9与上个数据不同。
注意第一行没有数要输出,但也要输出一个空行。
【数据范围】
Solution
容易想到一种做法,每次产生了两个数 ⌊ p x ⌋ \lfloor px\rfloor ⌊px⌋ 和 x − ⌊ p x ⌋ x-\lfloor px \rfloor x−⌊px⌋ 不作 + q +q +q 处理,可看作产生了两个值为 ⌊ p x ⌋ − q \lfloor px \rfloor - q ⌊px⌋−q 和 x − ⌊ p x ⌋ − q x - \lfloor px \rfloor -q x−⌊px⌋−q 的数,并把整个集合 + q +q +q 。
所以我们用一个变量 d e l t a delta delta 存储整个集合的变化量,利用大根堆,每一秒的操作为:
- 取出堆顶最大值 x x x,加上变化量 d e l t a delta delta
- 将新增的两个数值 ⌊ p x ⌋ − d e l t a − q \lfloor px \rfloor-delta-q ⌊px⌋−delta−q 和 x − ⌊ p x ⌋ − d e l t a − q x-\lfloor px\rfloor-delta-q x−⌊px⌋−delta−q 加入堆中
- 将变化量更新, d e l t a = d e l t a + q delta = delta +q delta=delta+q
算法时间复杂度 O ( m log n ) O(m\log n) O(mlogn) ,但 m ≤ 7 ∗ 1 0 6 m \le 7*10^6 m≤7∗106 可能会超时,因此进行优化:
考虑被先后取出的两个数 x 1 , x 2 x_1, x_2 x1,x2 ,可知 x 1 ≥ x 2 x_1\ge x_2 x1≥x2 ,又 0 < p < 1 0<p<1 0<p<1,则在 x 2 x_2 x2 被取出时有
⌊
p
x
1
⌋
+
q
=
⌊
p
x
1
+
q
⌋
≥
⌊
p
x
2
+
p
q
⌋
=
⌊
p
(
x
2
+
q
)
⌋
\lfloor px_1\rfloor+q=\lfloor px_1+q\rfloor\ge\lfloor px_2+pq\rfloor=\lfloor p(x_2+q)\rfloor
⌊px1⌋+q=⌊px1+q⌋≥⌊px2+pq⌋=⌊p(x2+q)⌋
又有
x
1
−
x
2
≥
p
(
x
1
−
x
2
)
x_1-x_2 \ge p(x_1-x_2)
x1−x2≥p(x1−x2),即
x
1
−
p
x
1
≥
x
2
−
p
x
2
≥
x
2
−
p
(
x
2
+
q
)
x_1-px_1\ge x_2-px_2\ge x_2-p(x_2+q)
x1−px1≥x2−px2≥x2−p(x2+q),则有
x 1 − ⌊ p x 1 ⌋ + q = ⌊ x 1 − p x 1 + q ⌋ ≥ ⌊ x 2 − p ( x 2 + q ) + q ⌋ = x 2 + q − ⌊ p ( x 2 + q ) ⌋ x_1-\lfloor px_1\rfloor+q=\lfloor x_1-px_1+q\rfloor\ge\lfloor x_2-p(x_2+q)+q\rfloor=x_2+q-\lfloor p(x_2+q)\rfloor x1−⌊px1⌋+q=⌊x1−px1+q⌋≥⌊x2−p(x2+q)+q⌋=x2+q−⌊p(x2+q)⌋
所以,每次取出一个数分割成的两个数分别是递减的,而我们从原来的集合中取出的数也应是递减的,因此就有了如下算法:
构造三个队列 A , B , C A,B,C A,B,C,分别存储原集合(降序排列),每次产生的 ⌊ p x ⌋ \lfloor px\rfloor ⌊px⌋ 的值,每次产生的 x − ⌊ p x ⌋ x-\lfloor px\rfloor x−⌊px⌋ 的值,则由于刚才证明的降序的性质,每一秒的最大值就是 A , B , C A,B,C A,B,C 的队头的最大值,之后再将本次新增的两个值加入 B , C B,C B,C 队列。
再结合开头提到的 d e l t a delta delta ,故每次加入队列 B , C B,C B,C 的数要换为 ⌊ p x ⌋ − q \lfloor px \rfloor - q ⌊px⌋−q 和 x − ⌊ p x ⌋ − q x - \lfloor px \rfloor -q x−⌊px⌋−q ,取出时再加上 d e l t a delta delta 即可。
Code
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int N = 1e5 + 5, M = 7e6 + 5;
int n, m, q, u, v, t;
int A[N], B[M], C[M];
int ha, hb, hc, ta, tb, tc;
int delta;
int get_max()
{
int x = -1e9;
if(ha <= ta) x = max(x, A[ha]);
if(hb <= tb) x = max(x, B[hb]);
if(hc <= tc) x = max(x, C[hc]);
if(ha <= ta && x == A[ha]) ha ++ ;
else if(hb <= tb && x == B[hb]) hb ++ ;
else if(hc <= tc && x == C[hc]) hc ++ ;
return x;
}
int main()
{
scanf("%d%d%d%d%d%d", &n, &m, &q, &u, &v, &t);
for(register int i = 1; i <= n; i ++ ) scanf("%d", &A[i]);
sort(A + 1, A + 1 + n, greater<int>());
ha = hb = hc = 1; ta = n;
for(register int i = 1; i <= m; i ++ )
{
int x = get_max() + delta;
if(i % t == 0) printf("%d ", x);
int k = (long long) x * u / v;
delta += q;
B[++tb] = k - delta;
C[++tc] = x - k - delta;
}
puts("");
for(register int i = 1; i <= n + m; i ++ )
{
int x = get_max() + delta;
if(i % t == 0) printf("%d ", x);
}
puts("");
return 0;
}