原题链接:https://www.acwing.com/problem/content/description/135/
思路:
1.如果q=0,即蚯蚓不会变长,那么就只是每次查询最大值,插入新的值。相当于维护一个集合。
2.如果q>0,那么每次选择最长的蚯蚓切断后,新产生的蚯蚓长度分别为px和x-px,并且其余蚯蚓会变长q,那么为了方便维护,我们设新产生的两只蚯蚓的长度分别为px-q和x-px-q,那么我们就可以对整个集合加上q。那么如何选择每次的最长的蚯蚓呢?我们可以建立三个队列,分别存储原来集合的蚯蚓(先按从大到小排序),新产生的px的蚯蚓,新产生的x-px的蚯蚓。由于每次选的都是最大值,因为p在0-1之间,并且这次的最大值选了,下次的肯定没这次大,所以新产生的两个蚯蚓集合同样满足递减规律,因此每次的最大值必是三个队首元素之一。
代码如下:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,m,q,u,v,t;
#define p u/v
const int maxn = 1e7+10;
ll f[maxn];
queue<ll> q1,q2,q3;
int cmp(int x, int y){
return x>y;
}
ll work(ll t){
ll x=-1,a=-1,b=-1,c=-1;
if(!q1.empty()) a=q1.front()+t*q;//然后把整个集合都加上q
if(!q2.empty()) b=q2.front()+t*q;
if(!q3.empty()) c=q3.front()+t*q;
x=max(a,max(b,c));
if(x==a) q1.pop();
else if(x==b) q2.pop();
else q3.pop();
return x;//找出最大值
}
int main(){
cin>>n>>m>>q>>u>>v>>t;
for(int i=1;i<=n;i++){
cin>>f[i];
}
sort(f+1,f+1+n,cmp);//从大到小排序
for(int i=1;i<=n;i++){
q1.push(f[i]);
}
for(int i=1;i<=m;i++){
ll x=work(i-1);//找出每个时刻的最大值
if(!(i%t)) cout<<x<<" ";//输出格式
ll now1=x*p;
ll now2=x-now1;
//不妨设产生了两个大小为px-q和x-px-q的新数
q2.push(now1-i*q);
q3.push(now2-i*q);
}
cout<<endl;
for(int i=1;i<=(n+m);i++){//输出所有蚯蚓的长度
ll x=work(m);
if(i%t==0) cout<<x<<" ";
}
return 0;
}