Luogu P2827 [NOIp2016提高组]蚯蚓 | 神奇的队列

题目链接

80分思路:

弄一个优先队列,不停地模拟,切蚯蚓时就将最长的那一条出队,然后一分为二入队,简单模拟即可。还要弄一个标记,表示从开始到当前时间每一条蚯蚓应该加上的长度,操作时就加上,入队时就减去,输出时也要加上,这样就不用一个一个加了。

80分代码:(注意:手打堆貌似会更快一些,能拿到85分左右,原理跟优先队列一样)

#include<iostream>
#include<cstdio>
#include<fstream>
#include<algorithm>
#include<string>
#include<sstream>
#include<cstring>
#include<queue>
    using namespace std;
    priority_queue<int> d;
int main()
{
    int n=0,m=0,q=0,t=0,k=0;
    double u=0,v=0;
    scanf("%d%d%d%lf%lf%d",&n,&m,&q,&u,&v,&t);
    for(int i=1;i<=n;i++)
    {
        int a=0;
        scanf("%d",&a);
        d.push(a);//入队 
    }
    for(int i=1;i<=m;i++)
    {
        int w=d.top(),l1=0,l2=0;
        d.pop();
        w+=k;//加上标记 
        k+=q;//更新标记 
        l1=w*(u/v);//计算长度 
        l2=w-l1;
        d.push(l1-k);//一分为二入队 
        d.push(l2-k);
        if(i%t==0) printf("%d ",w);//同时输出这一秒切的蚯蚓的长度 
    }
    printf("
");//换行 
    for(int i=1;i<=n+m;i++) 
    {
        if(i%t==0) printf("%d ",d.top()+k);//输出m秒后每一条蚯蚓的长度 
        d.pop();//队首元素出队 
    }
    printf("
");//换行 
    return 0;
}

 

100分思路: 

三队列模拟。 

第一个队列存放原始的蚯蚓长度(已从大到小排序)。 

第二个队列存放蚯蚓被切后的一份的长度([px])。 

第三个队列存放蚯蚓被切后的另一份的长度(x-[px])。 

每次在三个队列的队头中取一个最大值并将其出队,然后将其分成两份分别存在第二、三个队列里。 

因为每一次我们都是切最长的,而当我们切下一条时两条原来属于上一条的蚯蚓又会增长,所以先切一定大于后切的,第二、三个队列也就是单调递减的了。 

除此之外,还要加一个标记,记录当前每一条蚯蚓应增加的长度,操作时就加上,入队时就减去,输出时也要加上,这样就不用一个一个加了。  

AC代码:

#include<iostream>
#include<cstdio>
#include<fstream>
#include<algorithm>
#include<string>
#include<sstream>
#include<cstring>
    using namespace std;
struct duilie//手打队列 
{
    int head;//队首 
    int tail;//队尾 
    int d[7100005];//队列 
}dl[3];
int main()
{
    dl[0].head=dl[1].head=dl[2].head=1;//初始化队首队尾 
    dl[0].tail=dl[1].tail=dl[2].tail=1;
    int n=0,m=0,q=0,t=0,k=0;
    double u=0,v=0;
    scanf("%d%d%d%lf%lf%d",&n,&m,&q,&u,&v,&t);
    for(int i=1;i<=n;i++)
    {
        int a=0;
        scanf("%d",&a);
        dl[0].d[dl[0].tail++]=a;//入队 
    }
    sort(dl[0].d+dl[0].head,dl[0].d+dl[0].tail,greater<int>());//从大到小排序 
    for(int i=1;i<=m;i++)
    {
        int x=-2147483647,y=0,l1=0,l2=0;
        for(int j=0;j<3;j++)//在三个队首中取最大值 
            if(dl[j].head<dl[j].tail&&dl[j].d[dl[j].head]>x)
            {
                x=dl[j].d[dl[j].head];
                y=j;
            }
        dl[y].head++;//将最大值出队 
        x+=k;//加上当前标记 
        k+=q;//更新标记 
        l1=x*(u/v);//计算一段蚯蚓的长度 
        l2=x-l1;//计算另一段蚯蚓的长度 
        dl[1].d[dl[1].tail++]=l1-k;//分别入队 
        dl[2].d[dl[2].tail++]=l2-k;
        if(i%t==0) printf("%d ",x);//同时输出这一秒切的蚯蚓的长度 
    }
    printf("
");//记得换行 
    for(int i=1;i<=n+m;i++)//输出m秒后每只蚯蚓的长度 
    {
        int x=-2147483647,y=0;
        for(int j=0;j<3;j++)//在队首中取最大值 
            if(dl[j].head<dl[j].tail&&dl[j].d[dl[j].head]>x)
            {
                x=dl[j].d[dl[j].head];
                y=j;
            }
        dl[y].head++;//将最大值出队 
        if(i%t==0) printf("%d ",x+k);//输出 
    }
    printf("
");//记得换行 
    return 0;
}
原文地址:https://www.cnblogs.com/wozaixuexi/p/8457394.html