技巧题
初看时觉得用堆,但是m=7e6,貌似刚好卡log。于是只能另寻出路。
我们用堆的是要维护最大值,因为蚯蚓的长度每次都会变。
但是题目有这么一句话:
除了刚刚产生的两只新蚯蚓,其余蚯蚓的长度都会增加q(是一个非负整常数)。
也就是说,刚切的是不会涨长度的。而我们只需要它们之间的大小关系。因此我们只需考虑长度之间的差值。
那么,给所有蚯蚓的长度+q=给那两只的长度-q。
我们可以开三个数组,一个存开始时的蚯蚓,一个存切过后长度=[px]的蚯蚓,一个存长度=x-[px]的蚯蚓。
不难发现,这三个数组是分别递减的。
于是我们只需要每次在这三个数组的头取蚯蚓即可。输出时再加回去就行了。
时间复杂度 O(m) O ( m ) 。
代码(BZOJ行末不能有空格,而且第二行不能有换行符。别问我怎么知道的):
#include<cstdio>
#include<cstring>
#include<algorithm>
#define MAXN 7100000
using namespace std;
struct earthworm{
int p[MAXN+5];
int r,w;
};
int n,m,q,u,v,t;
earthworm a,b,c;
inline char readc(){
static char buf[100000],*l=buf,*r=buf;
if (l==r) r=(l=buf)+fread(buf,1,100000,stdin);
if (l==r) return EOF; return *l++;
}
inline int _read(){
int num=0; char ch=readc();
while (ch<'0'||ch>'9') ch=readc();
while (ch>='0'&&ch<='9'){ num=num*10+ch-48; ch=readc(); }
return num;
}
bool comp(int x,int y){
return x>y;
}
int main(){
n=_read(); m=_read(); q=_read(); u=_read(); v=_read(); t=_read();
for (int i=1;i<=n;i++)
a.p[++a.w]=_read();
sort(a.p+1,a.p+n+1,comp);
for (int i=1;i<=m;i++){
int x=-0x7fffffff;
if (a.r<a.w) x=max(a.p[a.r+1],x);
if (b.r<b.w) x=max(b.p[b.r+1],x);
if (c.r<c.w) x=max(c.p[c.r+1],x);
if (i%t==0) printf("%d ",x+(i-1)*q);
int px=(double)u/v*(x+(i-1)*q);
if (a.r<a.w&&x==a.p[a.r+1]) a.r++;
else if (b.r<b.w&&x==b.p[b.r+1]) b.r++;
else c.r++;
b.p[++b.w]=px-i*q; c.p[++c.w]=x-px-q;
}
printf("\n");
int node=0;
while (a.r<a.w||b.r<b.w||c.r<c.w){
node++;
int x=-0x7fffffff;
if (a.r<a.w) x=max(a.p[a.r+1],x);
if (b.r<b.w) x=max(b.p[b.r+1],x);
if (c.r<c.w) x=max(c.p[c.r+1],x);
if (node%t==0) printf("%d ",x+m*q);
if (a.r<a.w&&x==a.p[a.r+1]) a.r++;
else if (b.r<b.w&&x==b.p[b.r+1]) b.r++;
else if (c.r<c.w) c.r++;
}
printf("\n");
return 0;
}