解题报告
取最小值就直接想到堆,但是注意m为 7∗106 ,也就是最后可能会有 107 以上的个数,堆的 O(nlogn) 显然会TLE,所以需要更优的方案。
首先会发现蚯蚓的增长是很麻烦的,但是这是相对的。所以可以直接让被选出的蚯蚓减少长度而不是让其他蚯蚓增加长度。也就是说所有的蚯蚓其实都是”最初的长度”,然后要切的时候加回原长,切完后的两段又捡回”初始长度”。
然后再思考,每次切完蚯蚓后,两段的长度都不会比原串长。所以其实蚯蚓的“原长”(注意是原长,不是现在的长度,看样例就知道)是递减的,然后,就可以直接开3个队列分别处理0:原长,1:一段和2:另一段。每次3个队列头中找最长的,然后分成两端,分别放在1,2队列后面。
然后注意,因为捡回原长后有可能是负的,也有可能负的太大了。所以需要在找出最大值的时候把初始的负值越小越好, −109 会被洛谷卡掉,UOJ hack掉,所以直接 −(231−1) 。查了两天代码的惨痛教训。
复杂度:
时间:
O(m)
;
空间:
O(3m)
;
#include<cstdio>
#include<algorithm>
#define LL long long
#define INF (((1<<30)-1)<<1)+1
using namespace std;
int n,m,p,q,t,u,now,que[3][7000005],hed[3],til[3];
inline char nc(){
static char buf[100000],*pa=buf,*pb=buf;
return pa==pb&&(pb=(pa=buf)+fread(buf,1,100000,stdin),pa==pb)?EOF:*pa++;
}
inline void readi(int &x){
x=0; char ch=nc();
while ('0'>ch||ch>'9') ch=nc();
while ('0'<=ch&&ch<='9') {x=x*10+ch-'0'; ch=nc();}
}
inline bool cmp(const int x,const int y){return x>y;}
void _init(){
freopen("earthworm.in","r",stdin);
freopen("earthworm.out","w",stdout);
readi(n); readi(m); readi(u); readi(p); readi(q); readi(t);
for (int i=1;i<=n;i++) readi(que[0][i]); sort(que[0]+1,que[0]+n+1,cmp);
}
inline int geti(){
int tem=-INF,ans;
for (int i=0;i<3;i++) if (hed[i]<=til[i]&&que[i][hed[i]]>tem) {tem=que[i][hed[i]]; ans=i;}
return ans;
}
void _solve(){
hed[0]=hed[1]=hed[2]=1; til[1]=til[2]=now=0; til[0]=n;
for (int i=1,ti=t;i<=m;i++,now+=u){
int x=geti(),y=que[x][hed[x]++]+now; if (i==ti) {printf("%d ",y); ti+=t;}
int L=(LL)y*p/q,R=y-L; que[1][++til[1]]=L-now-u; que[2][++til[2]]=R-now-u;
}
printf("\n");
for (int i=1,ti=t;i<=n+m;i++){
int x=geti(),y=que[x][hed[x]++]+now; if (i==ti){ti+=t; printf("%d ",y);}
}
}
int main()
{
_init();
_solve();
return 0;
}