zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    数据库事务
    什么场景应该用 MongoDB ?
    ES6 箭头函数 =>
    HTML5 <template>标签元素简介
    ES6新特性:使用新方法定义javascript的Class
    Windows平台下Git(gitblit)服务器搭建
    利用WiFi Pineapple Nano渗透客户端获取SHELL
    出现 “未能创建此平台,因为已存在同名的解决方案平台”提示,是什么原因?
    VS2010 常用快捷键
    C# WINFORM 捕获全局异常
  • 原文地址:https://www.cnblogs.com/wozaixuexi/p/8457394.html
Copyright © 2011-2022 走看看