蚯蚓
(File IO): input:earthworm.in output:earthworm.out
Time Limits: 1s Memory Limits: 512MB
Description
Input
Output
Sample Input
Sample Input1:
3 7 1 1 3 1
3 3 2
Sample Input2:
3 7 1 1 3 2
3 3 2
Sample Input3:
3 7 1 1 3 9
3 3 2
Sample Output
Sample Output1:
3 4 4 4 5 5 6
6 6 6 5 5 4 4 3 2 2
Sample Output2:
4 4 5
6 5 4 3 2
Sample Output3:
2
Hint
Data Constraint
解题思路
一看就是要让人线性求解的题目:
维护一条链,存蚯蚓进来时的长度和进来时的时间,链首到链尾是按照蚯蚓长度大到小的顺序,在维护两个指针a,b表示将链首切成两段后,第一段小于蚯蚓las[a]的长度且大于蚯蚓a的长度,第二段小于蚯蚓las[b]的长度且大于蚯蚓b的长度,这样的话,第一段就可以查到las[a]与a之间,第二段可以查到las[b]与b之间,达成了o(n+m)
Codes:
#include<cmath>
#include<cstdio>
#include<cstring>
using namespace std;
int ti[21000010],len[21000010],las,a,b,top,n,m,q,t,nex[21000010],le[21000010],now,te,na,nb;
double u,v,p;
void swap(int &a,int &b){int c=a;a=b;b=c;}
void qs(int h,int t)
{
int l=h,r=t,m=le[(h+t)>>1];
do
{
while(le[l]>m)l++;
while(le[r]<m)r--;
if(l<=r)swap(le[l++],le[r--]);
}while(l<=r);
if(h<r)qs(h,r);if(l<t)qs(l,t);
}
int main()
{
freopen("earthworm.in","r",stdin);
freopen("earthworm.out","w",stdout);
scanf("%d%d%d%lf%lf%d",&n,&m,&q,&u,&v,&t);
p=u/v;
for(int i=1;i<=n;i++)scanf("%d",&le[i]);
qs(1,n);
te=now=0;
for(int i=1;i<=n;i++)
{
top++;
nex[las]=top;
len[top]=le[i];
ti[top]=0;
las=top;
}
a=b=1;na=nb=nex[1];
int tem,temp;
for(int i=1;i;i=nex[i])
{
temp=i;
tem++;
if(tem>m)break;
int x=len[i]+(now-ti[i])*q;
if(tem%t==0)printf("%d ",x);
now++;
int s1=floor((double(x))*p),s2=x-s1;
for(;;)
{
int l1=len[na]+(now-ti[na])*q;
if(!na || l1<=s1)
{
top++;
nex[a]=top;
nex[top]=na;
ti[top]=now;
len[top]=s1;
if(nex[las])las=nex[las];
if(!na)na=las;
break;
}else{a=na,na=nex[na];}
}
na=nex[a];nb=nex[b];
for(;;)
{
int l1=len[nb]+(now-ti[nb])*q;
if(!nb || l1<=s2)
{
top++;
nex[b]=top;
nex[top]=nb;
ti[top]=now;
len[top]=s2;
if(nex[las])las=nex[las];
if(!nb)nb=las;
break;
}else{b=nb,nb=nex[nb];}
}
na=nex[a];nb=nex[b];
}
printf("\n");
tem=0;
for(int i=temp;i;i=nex[i])
{
tem++;
if(tem%t==0)printf("%d ",len[i]+(now-ti[i])*q);
}
}