【NOIP2016D2T2蚯蚓】一道NOIP真题

就是这样的一道题。大家实在想看本题的类型可以看每篇文章下面若隐若现的标签(orz 虽然应该没什么人看蒟蒻的博客) 单调队列 Luogu2827 LOJ2362 这道题和那道合并果子基本上就是一模(mu)一样。那道题是找最小的两个果子合并,甚至都可以用堆来做,这道题堆貌似只有80分(要是叫你堆就水过去了他还干嘛orz )。 由于每一次被切的比例是固定的,那么我们可以发现一个单调性-->先被切开的两段比后被切开的两段大。这也很好证明,他们被切开就必定要错过一次增加长度,于是他们在增加的意义下是相同的,而我们是优先选择较大的切开,那么就一定有这个单调性。 于是乎我们开三个队列,表示原本队列(我们可以先sort一下保证其单调性),被切开的前一段的队列,被切开的后一段的队列,然后我们每次找出三个中最大的那个切开,再甩进队尾就可以了。 对于添加,由于是整体添加,仅仅只有刚刚切开的错过添加,那么我们完全可以整一个全局变量Q的东东,在添加进队列的时候减去这时候的Q,出来的时候加这时候的Q。 时间复杂度O(nlogn + n + m) nlogn是初始n个数sort 带过来的
#include<stdio.h> 
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
const int maxn = 100005;
int n,m,q,u,v,t;
double p;
int a[maxn];
queue<int>qu[3];
int tim;
int Q; 
int main()
{
	scanf("%d%d%d%d%d%d",&n,&m,&q,&u,&v,&t);
	p=(double)u/(double)v;
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
	}
	sort(a+1,a+1+n);
	for(int i=n;i>=1;i--) qu[0].push(a[i]);
	for(int i=1;i<=m;i++) 
	{
		int zqmx = 0;
		for(int i=0;i<3;i++) 
		{
			if(qu[i].size()) 
			{
				zqmx = max(zqmx,qu[i].front()+Q);
			}
		} int zz;
		for(int i=0;i<3;i++)
		{
			if(qu[i].size())
			{
				if(qu[i].front()+Q==zqmx) { zz=i; break; }
			}
		}
		if(i%t==0)
		{
			printf("%d ",zqmx);
		}
		qu[zz].pop();
		int qyd = (int)floor( (double)(zqmx)*p );
		Q+=q;
		qu[1].push(qyd-Q); qu[2].push(zqmx-qyd-Q);  
	}
	puts("");
	int tim = (n+m)/t;
	for(int i=1;i<=tim*t;i++)
	{
		int zqmx = 0;
		for(int i=0;i<3;i++) 
		{
			if(qu[i].size()) 
			{
				zqmx = max(zqmx,qu[i].front()+Q);
			}
		} int zz;
		for(int i=0;i<3;i++)
		{
			if(qu[i].size())
			{
				if(qu[i].front()+Q==zqmx) { zz=i; break; }
			}
		}
		if(i%t==0)
		{
			printf("%d ",zqmx);
		}
		qu[zz].pop();
	}
}
 
posted @ 2018-07-31 23:57  Newuser233  阅读(4)  评论(0)    收藏  举报