努力刷完NOIP提高组题目ing…
50~60分算法:直接用堆/优先队列模拟
100分算法:观察题目,发现其中隐含的单调性。
设两条蚯蚓长度为
a
,
b
a,b
a,b,其中
a
>
b
a > b
a>b。
则
a
a
a被切掉时长度分别为
p
a
,
(
1
−
p
)
a
pa, (1 - p)a
pa,(1−p)a,过t秒之后长度为
p
a
+
t
q
,
(
1
−
p
)
a
+
t
q
pa+tq, (1 - p)a +tq
pa+tq,(1−p)a+tq
此时
b
b
b被取出,长度
b
+
t
q
b + tq
b+tq,被切之后长度分别为
p
(
b
+
t
q
)
,
(
1
−
p
)
b
+
t
q
p(b + tq),(1 - p)b + tq
p(b+tq),(1−p)b+tq
显然a的两段长度还是大于b的两段。
由此,我们可以建立3个队列,分别是没切过的蚯蚓,切过之后较长的一段蚯蚓,切过之后较短的一段蚯蚓。
- 每次比较三个队列的队头(因为满足单调性),取出最长的一段切掉,把长的一段和短的一段分别加到两个队列中。
注意细节。
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
int q[3][20000001], l[3], r[3];
inline int read(){
int k = 0; char ch = getchar();
while(ch < '0' || ch > '9') ch = getchar();
while(ch >= '0' && ch <= '9') k = (k<<3) + (k<<1) + ch - 48, ch = getchar();
return k;
}
inline bool cmp(int a, int b){
return a > b;
}
inline int Find_Max(){
int Max = -0x7fffffff, opt = 0;
for(int i = 0; i < 3; i++)
if(l[i] <= r[i] && q[i][l[i]] > Max)
Max = q[i][l[i]], opt = i;
return opt;
}
int main(){
int n = read(), m = read(), R = read();
int U = read(), V = read(), t = read();
for(int i = 1; i <= n; i++){
q[0][i] = read();
}
sort(q[0] + 1, q[0] + n + 1, cmp); l[0] = 1, r[0] = n;
l[1] = l[2] = 1, r[1] = r[2] = 0;
int tag = 0;
for(int i = 1; i <= m; i++){
int opt = Find_Max();
int u = q[opt][l[opt]++] + tag; tag += R;
int Worm1 = (int)((long long)u * U / V), Worm2 = u - Worm1;
if(Worm2 > Worm1) swap(Worm2, Worm1);
q[1][++r[1]] = Worm1 - tag, q[2][++r[2]] = Worm2 - tag;
if(i % t == 0) printf("%d ", u);
}
printf("\n");
for(int i = 1; i <= n + m; i++){
int opt = Find_Max();
if(i % t == 0) printf("%d ", q[opt][l[opt]] + tag);
l[opt]++;
}
return 0;
}