Live2D

【NOIP2017】蚯蚓

有n只蚯蚓,每次选取一条最长的,按比例切成两半
然后其它没有被切的全部增加一个长度q
问每次切的是哪条蚯蚓,最后所有蚯蚓的长度是多少

朴素的暴力想法:
类似于合并石子,使用一个堆来储存长度,每次取出堆顶切成两半
其它蚯蚓增加长度=这两半减少长度
输出的时候加上总增加长度即可

但考虑一下,需要优先队列来储存吗?
可以证明,无论哪种情况,先切的蚯蚓两半的长度一定大于后切的蚯蚓两半的长度
自带单调性啊

所以我们直接开三个数组,分别存原长,切了后第一段长度,切了后第二段长度
每次取出三个数组第一个元素的最大值操作即可

这三个数组不是堆,因为操作过程本身就保证了单调性

代码:

#include<bits/stdc++.h>
#define N 10000005
using namespace std;

int n,m,q,u,v,t,x,y;
int a[N],b[N],c[N];
int head=1,tail,head1=1,head2=1,tail1=0,tail2=0;
int lst[N*10],cnt;
int sigma;

template<class T>inline void read(T &res)
{
	char c;T flag=1;
	while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
	while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
}

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

int main()
{
//	freopen("testdata.in","r",stdin);
//	freopen("testdata.txt","w",stdout);
	read(n);read(m);read(q);
	read(u);read(v);read(t);
	double p=(double)u/v;
	
	for(register int i=1;i<=n;++i) read(a[i]);
	tail=n;
	sort(a+1,a+n+1,cmp);
	int top;
	for(register int i=1;i<=m;++i)
	{
		if(head>tail)
		{
			if(b[head1]>c[head2]) top=b[head1++];
			else top=c[head2++];
		}
		else if(a[head]>=b[head1]&&a[head]>=c[head2]) top=a[head++];
		else if(b[head1]>=c[head2]&&a[head]<=b[head1]) top=b[head1++];
		else top=c[head2++];
		
		top+=sigma;
		x=floor(p*(double)top),y=top-x;
		sigma+=q;
		b[++tail1]=x-sigma;
		c[++tail2]=y-sigma;
		if(i%t==0) printf("%d ",top);
	}
	puts("");
	for(register int i=head;i<=tail;++i) lst[++cnt]=a[i];
	for(register int i=head1;i<=tail1;++i) lst[++cnt]=b[i];
	for(register int i=head2;i<=tail2;++i) lst[++cnt]=c[i];
	sort(lst+1,lst+cnt+1,cmp);
//	for(register int i=1;i<=cnt;++i) cout<<lst[i]+sigma<<" ";
	int now=0;
	for(register int i=1;i<=cnt;++i)
	{
		now++;
		if(i%t==0) printf("%d ",lst[now]+sigma);
	}
	return 0;
}
posted @ 2019-11-10 21:27  tqr06  阅读(164)  评论(0编辑  收藏  举报