蚯蚓

蚯蚓

(File IO): input:earthworm.in output:earthworm.out

Time Limits: 1s Memory Limits: 512MB

Description
Description
Input
Input
Output
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
Hint1
Hint2
Hint3
Data Constraint
Data1
Data2


解题思路


一看就是要让人线性求解的题目:

维护一条链,存蚯蚓进来时的长度和进来时的时间,链首到链尾是按照蚯蚓长度大到小的顺序,在维护两个指针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);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值