AcWing 133 蚯蚓 (队列)

https://www.acwing.com/problem/content/description/135/

优先队列,每次将最长的蚯蚓取出来,切开后减去当前的偏移量,再放回队列
但 \(m\) 的范围是 \(7e6\),显然需要线性做法

线性做法,那就需要考虑一下蚯蚓长度的单调性了,
可以证明,如果 \(x1 > x2\) ,那么新产生的两个蚯蚓长度也是单调递减的
所以就可以维护三个长度递减的队列,每次记得加上偏移量即可

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<stack>
#include<queue>
using namespace std;
typedef long long ll;

const int maxn = 100010;

int n, m, Q, v, u, t, delta;
double p;
int a[maxn];

queue<int> q[4];

vector<int> ans1, ans2;

bool cmp(int a, int b){ return a > b; }

ll read(){ ll s=0,f=1; char ch=getchar(); while(ch<'0' || ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0' && ch<='9'){ s=s*10+ch-'0'; ch=getchar(); } return s*f; }

int main(){
	delta = 0;
	n = read(), m = read(), Q = read(), u = read(), v = read(), t = read();
	p = (1.0 * u) / (1.0 * v);
	
	for(int i=1;i<=n;++i) a[i] = read();
	
	sort(a + 1, a + 1 + n, cmp);
	for(int i=1;i<=n;++i) q[0].push(a[i]);
	
	int num, x, part1, part2;
	if(m!=0){
		x = q[0].front();
		q[0].pop();
		part1 = p * x;
		part2 = x - part1;
		delta = Q;
		q[1].push(part1 - delta);
		q[2].push(part2 - delta);
		if(t == 1) ans1.push_back(x);
		
		for(int i=2;i<=m;++i){
			if(!q[0].empty()) num = 0, x = q[0].front();
			else num = 1, x = q[1].front();
			if(q[1].front() > x){
				x = q[1].front();
				num = 1;
			}
			if(q[2].front() > x){
				x = q[2].front();
				num = 2;
			}
		
			q[num].pop();
			if(i % t == 0) ans1.push_back(x + delta);
			part1 = p * (x + delta);
			part2 = (x + delta) - part1;
			delta += Q;
			q[1].push(part1 - delta);
			q[2].push(part2 - delta);
		}
		
		int num, x;
		while(!q[0].empty() || !q[1].empty() || !q[2].empty()){
			if(!q[0].empty()) num = 0, x = q[0].front();
			else if(!q[1].empty()) num = 1, x = q[1].front();
			else num = 2, x = q[2].front();
			
			if(!q[1].empty() && q[1].front() > x){
				x = q[1].front();
				num = 1;
			}
			if(!q[2].empty() && q[2].front() > x){
				x = q[2].front();
				num = 2;
			}
			ans2.push_back(x + delta);
			q[num].pop();
		}
		
		for(int i=0;i<ans1.size();++i){
			printf("%d ",ans1[i]);
		}printf("\n");
		for(int i=0;i<ans2.size();++i){
			if((i+1) % t == 0) printf("%d ",ans2[i]); 
		}printf("\n");
	}else{
		printf("\n");
		for(int i=1;i<=n;++i) if(i % t == 0) printf("%d ",a[i]); printf("\n");
	}
	
	return 0;
}
上一篇:【操作系统】-同步互斥-【经典问题】-单生产者单消费者问题


下一篇:喝汽水,1瓶汽水1元,2个空瓶可以换一瓶汽水,给20元,可以多少汽水