LOJ-2362 蚯蚓 队列优化
题意
给出(n)个蚯蚓,常数(q),$ 0 < p < 1(,现进行)m(此操作,每次操作取当前最长的蚯蚓,对于最长的蚯蚓将其分为两部分,长度分别为)lfloorfrac{x}{p} floor,x - lfloorfrac{x}{p} floor$ ,且其他蚯蚓的长度都加上(q),现询问每次操作选出的最长的蚯蚓(操作前),以及最终的每个蚯蚓的长度
[q = frac{u}{v}
]
[1 leq n leq 10^5\
0 leq m leq 7 imes 10^6\
0 < u,v < 10^9\
0 leq qle 200\
1leq tleq71\
0leq a_i leq 10^8
]
分析
此题很容易想到维护一个堆来做,考虑到复杂度显然不可做
于是寻找性质来优化
易证得 后面切割的蚯蚓的前后部分分别小于等于前面切割的蚯蚓的前后部分
于是可以利用这个性质维护三个单调递减的队列,分别用于存储原始的蚯蚓,切割后的前半部分的蚯蚓,切割后的后半部分的蚯蚓
每次只需要要比较三个队列的队首哪个最大即可
对于全体加上一个值,可以利用一个全局变量(tag)进行标记,对切割后的减去(q)即可。真实长度即相对的长度加上(tag)
于是变成了一道模拟题,模拟了好久。。唉
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
typedef long long ll;
ll rd(){
ll x = 0;
char ch = getchar();
while(ch < '0' || ch > '9') {
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = x * 10 + ch - '0';
ch = getchar();
}
return x;
}
const int maxn = 7e6 + 1e5 + 5;
int que1[maxn];
int que2[maxn];
int que3[maxn];
ll tag;
signed main(){
int n = rd();
int m = rd();
int q = rd();
int u = rd();
int v = rd();
int t = rd();
for(int i = 1;i <= n;i++)
que1[i] = rd();
sort(que1 + 1,que1 + n + 1,greater<int>{});
int head1 = 1,tail1 = n;
int head2 = 1,tail2 = 0;
int head3 = 1,tail3 = 0;
for(int i = 1;i <= m;i++){
int n1 = tail1 >= head1 ? que1[head1] : -1e18;
int n2 = tail2 >= head2 ? que2[head2] : -1e18;
int n3 = tail3 >= head3 ? que3[head3] : -1e18;
if(n1 > n2) {
if(n1 > n3) {
que2[++tail2] = (que1[head1] + tag) * u / v,que3[++tail3] = que1[head1] + tag - (que1[head1] + tag) * u / v,head1++;
}
else {
int tmp = que3[head3] + tag;
que2[++tail2] = tmp * u / v;
que3[++tail3] = tmp - tmp * u / v;
head3++;
}
}
else if(n2 > n3){
int tmp = que2[head2] + tag;
que2[++tail2] = tmp * u / v;
que3[++tail3] = tmp - tmp * u / v;
head2++;
}
else {
int tmp = que3[head3] + tag;
que2[++tail2] = tmp * u / v;
que3[++tail3] = tmp - tmp * u / v;
head3++;
}
que2[tail2] -= q;
que3[tail3] -= q;
que2[tail2] -= tag;
que3[tail3] -= tag;
if(i % t == 0)
printf("%lld ",tag + max(n1,max(n2,n3)));
tag += q;
/*
for(int i = head1;i <= tail1;i++)
cout << que1[i] + tag << ' ';
puts("");
for(int i = head2;i <= tail2;i++)
cout << que2[i] + tag << ' ';
puts("");
for(int i = head3;i <= tail3;i++)
cout << que3[i] + tag << ' ';
puts("");*/
}
puts("");
for(int i = 1;i <= m + n;i++){
int n1 = (tail1 >= head1 ? que1[head1] : -1e18);
int n2 = (tail2 >= head2 ? que2[head2] : -1e18);
int n3 = (tail3 >= head3 ? que3[head3] : -1e18);
//cout << n1 << ' ' << n2 << ' ' << n3 << '
';
if(n1 > n2) {
if(n1 > n3) {
if(i % t == 0)
printf("%lld ",n1 + tag);
head1++;
}
else {
if(i % t == 0)
printf("%lld ",n3 + tag);
head3++;
}
}
else if(n2 > n3){
if(i % t == 0)
printf("%lld ",n2 + tag);
head2++;
}
else {
if(i % t == 0)
printf("%lld ",n3 + tag);
head3++;
}
}
}