【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;
}
$$\text{这里是tqr,联系我请加QQ735748368}$$