P2827 蚯蚓
题解
(不行,我先吐槽一下,因为少了两个等号我调了一个晚上!!!可恶啊(〃>皿<),35分到100分的差距!)
首先,我们可以先模拟一下切蚯蚓的过程,会发现,后切成蚯蚓肯定要比先切成蚯蚓短。假设现在有蚯蚓
a
,
b
a,b
a,b并且
L
a
>
L
b
L_a>L_b
La>Lb,对于第
i
i
i次切割,切割蚯蚓
a
a
a,长度为
L
a
L_a
La,将其切割为
x
=
p
⋅
L
a
x=p\cdot L_a
x=p⋅La和
y
=
L
a
−
x
y = L_a-x
y=La−x,对于第
j
(
i
<
j
≤
m
)
j(i<j\leq m)
j(i<j≤m)次切割,切割蚯蚓
b
b
b,将其切割为
x
1
=
p
⋅
L
b
x_1=p\cdot L_b
x1=p⋅Lb和
y
1
=
L
b
−
x
1
y_1 = L_b-x_1
y1=Lb−x1,此时之前第
i
i
i次切割的两条蚯蚓的长度应该为
x
+
(
j
−
i
)
x+(j-i)
x+(j−i)和
y
+
(
j
−
i
)
y+(j-i)
y+(j−i),因此有
{
p
⋅
L
a
+
(
j
−
i
)
>
p
⋅
L
b
+
(
j
−
i
)
L
a
⋅
(
1
−
p
)
+
(
j
−
i
)
>
L
b
⋅
(
1
−
p
)
+
(
j
−
i
)
\begin{cases} p\cdot L_a+(j-i)>p\cdot L_b+(j-i)\\\\ L_a\cdot (1-p)+(j-i)>L_b\cdot(1-p)+(j-i)\end{cases}
⎩⎪⎨⎪⎧p⋅La+(j−i)>p⋅Lb+(j−i)La⋅(1−p)+(j−i)>Lb⋅(1−p)+(j−i)
因此我们可以利用这个规律,将蚯蚓分为三部分:
1.从大到小排好序的未切割的蚯蚓
2.每次切割完蚯蚓长度相对短的蚯蚓
3.每次切割完蚯蚓长度相对长的蚯蚓
然后每次切割的时候在这三队里面选择最长的蚯蚓切割即可。
还有一点就是对于每次切割时未被切割的蚯蚓会增加长度 q q q,因为每次增加的时候是固定的 q q q,因此我们可以利用差分思想,标记增量,每次入队的时候减去,查询的时候再加上。
#include<bits/stdc++.h>
using namespace std;
const int N = 7000010;
int n,m,q,u,v,t,a[N],b[N],c[N];
int main() {
#ifndef ONLINE_JUDGE
freopen("input.in", "r", stdin);
#endif
vector<int> ans;
cin >> n >> m >> q >> u >> v >> t;
for (int i = 0; i < n; ++i)
cin >> a[i];
int front1 = 0, rear1 = n, front2 = 0, rear2 = 0, front3 = 0, rear3 = 0;
sort(a, a + n, greater<int>());
int tmp, sum = 0;
double p = 1.0 * u / v;
for (int i = 1; i <= m; ++i) {
if (front1 < rear1) {
if (a[front1] >= max(b[front2], c[front3])) {
tmp = a[front1++];
} else if (b[front2] >= max(a[front1], c[front3])) {
tmp = b[front2++];
} else {
tmp = c[front3++];
}
} else {
if (b[front2] > c[front3])
tmp = b[front2++];
else
tmp = c[front3++];
}
tmp += sum; //加上标记
sum += q; //更新标记
int x = floor(p * tmp), y = tmp - x;
x -= sum, y -= sum;
b[rear2++] = x, c[rear3++] = y;
if (i % t == 0)
cout << tmp << ' ';
}
puts("");
for (int i = front1; i < rear1; ++i)
ans.push_back(a[i]);
for (int i = front2; i < rear2; ++i)
ans.push_back(b[i]);
for (int i = front3; i < rear3; ++i)
ans.push_back(c[i]);
sort(ans.begin(), ans.end(), greater<int>());
for (int i = 0; i < ans.size(); ++i) {
if ((i + 1) % t == 0)
cout << ans[i] + sum << ' ';
}
return 0;
}