洛谷P2827 蚯蚓(隐藏的单调的队列)
原创
©著作权归作者所有:来自51CTO博客作者wx5e9d3f1cab2eb的原创作品,请联系作者获取转载授权,否则将追究法律责任
P2827 蚯蚓
题解
(不行,我先吐槽一下,因为少了两个等号我调了一个晚上!!!可恶啊(〃>皿<),35分到100分的差距!)
首先,我们可以先模拟一下切蚯蚓的过程,会发现,后切成蚯蚓肯定要比先切成蚯蚓短。假设现在有蚯蚓
并且
,对于第
次切割,切割蚯蚓
,长度为
,将其切割为
和
,对于第
次切割,切割蚯蚓
,将其切割为
和
,此时之前第
次切割的两条蚯蚓的长度应该为
和
,因此有

因此我们可以利用这个规律,将蚯蚓分为三部分:
1.从大到小排好序的未切割的蚯蚓
2.每次切割完蚯蚓长度相对短的蚯蚓
3.每次切割完蚯蚓长度相对长的蚯蚓
然后每次切割的时候在这三队里面选择最长的蚯蚓切割即可。
还有一点就是对于每次切割时未被切割的蚯蚓会增加长度
,因为每次增加的时候是固定的
,因此我们可以利用差分思想,标记增量,每次入队的时候减去,查询的时候再加上。
#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("", "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;
}