题意

  • 共有n条蚯蚓,切割m次,每次切当前所有蚯蚓中最长的一条,切割比例为p=u/v,即对于长x的蚯蚓,切成px(向下取整)和x-px两段
  • 特别的,长度为0也会被保留
  • 同时每次切割后,除了被切割的那一条,其它蚯蚓增长q的长度
  • 每切t次输出当前要切的这条蚯蚓的长度,最后输出长度从大到小排名t的整数倍的蚯蚓长度

思路

  • 最开始先读入所有蚯蚓,从大到小排序
  • 对于切割这件事,满足对切出来的两段中的任意一段,总有先切出来的比后切出来的更长,所以可以开两个队列维护切出来的两段,再加上没切的一共三个队列
  • 每次比较三个队列中的队首,找到最大的那个,切一半
  • 对于生长这件事,有两个思路处理,一个是开结构体,既存储长度还存储产生时间,最后统一计算;另一个思路是,把所有蚯蚓统一到相同时间,如:0时刻,每次切之前给它加加上生长时常,切完后,再削减长度至0时刻应有的长度;eg.20秒的时候,切出两条长度为10和20的蚯蚓,假设生长速度为1,那么这两条新产生的蚯蚓在入队的时候就应当更新为-10和0;表示0时刻它们的长度

代码

#include<bits/stdc++.h>
#define int long long
using namespace std;
int a[101010];
bool cmp(int a,int b){return a>b;}
signed main(){
	int n,m,q,u,v,t;
	scanf("%lld%lld%lld%lld%lld%lld",&n,&m,&q,&u,&v,&t);
	for(int i=0;i<n;i++){scanf("%lld",&a[i]);}
	sort(a,a+n,cmp);
	queue<int>b[3];
	for(int i=0;i<n;i++){b[0].push(a[i]);}

	for(int i=1;i<=m;i++){
		int idx,tp=-2e18;
		for(int j=0;j<3;j++){
			if(!b[j].empty()&&b[j].front()>tp){
				tp=b[j].front();
				idx=j;
			}
		}
		//统一到0时刻
		b[idx].pop();
		int px1=(tp+(i-1)*q)*u/v;
		int px2=(tp+(i-1)*q)-px1;
		b[1].push(px1-i*q);
		b[2].push(px2-i*q);
		if(i%t==0)printf("%lld ",tp+(i-1)*q);
	}
	printf("\n");
	for(int i=1;i<=n+m;i++){
		int idx,tp=-2e9;
		for(int j=0;j<3;j++){
			if(!b[j].empty()&&b[j].front()>tp){
				tp=b[j].front();
				idx=j;
			}
		}
		b[idx].pop();
		if(i%t==0)printf("%lld ",tp+(m*q));
	}
	return 0;
}

注意

  • 统一到0时刻就意味着可能出现负数,所以在找最大的过程中,初值要给一个很小的负数,如2e18;