• ACM/ICPC 之 优先级队列+设置IO缓存区(TSH OJ-Schedule(任务调度))


    一个裸的优先级队列(最大堆)题,但也有其他普通队列的做法。这道题我做了两天,结果发现是输入输出太过频繁,一直只能A掉55%的数据,其他都是TLE,如果将输入输出的数据放入缓存区,然后满区输出,可以将IO时间消耗降到很低。

    任务调度(Schedule)


    描述

    某高性能计算集群(HPC cluster)采用的任务调度器与众不同。为简化起见,假定该集群不支持多任务同时执行,故同一时刻只有单个任务处于执行状态。初始状态下,每个任务都由称作优先级数的一个整数指定优先级,该数值越小优先级越高若优先级数相等,则任务名ASCII字典顺序低者优先。此后,CPU等资源总是被优先级数最小的任务占用;每一任务计算完毕,再选取优先级数最小下一任务。不过,这里的任务在计算结束后通常并不立即退出,而是将优先级数加倍(加倍计算所需的时间可以忽略)并继续参与调度;只有在优先级数不小于2^32时,才真正退出

    你的任务是,根据初始优先级设置,按照上述调度原则,预测一批计算任务的执行序列。

    输入

    第一行为以空格分隔的两个整数n和m,n为初始时的任务总数,m为所预测的任务执行序列长度,每行末尾有一个换行符

    以下n行分别包含一个整数和一个由不超过8个小写字母和数字组成的字符串。前者为任务的初始优先级数,后者为任务名。数字和字符串之间以空格分隔

    输出

    最多m行,各含一个字符串。按执行次序分别给出执行序列中前m个任务的名称,若执行序列少于m,那么输出调度器的任务处理完毕前的所有任务即可。

    Example

    Input

    3 3
    1 hello
    2 world
    10 test
    

    Output

    hello
    hello
    world
    

    限制

    0 ≤ n ≤ 4,000,000

    0 ≤ m ≤ 2,000,000

    0 < 每个任务的初始优先级 < 2^32

    不会有重名的任务

    时间:2 sec

    内存:512 MB


      解题思路:

        首先是优先级队列(最大堆),关于该问题的讨论,可以参见我第一篇文章 算法手记 之 数据结构(堆)(POJ 2051)

        建堆算法和插入算法在听过邓俊辉老师的MOOC后进行了优化,批量建堆操作可以将时间度综合效率经过下滤优化至O(N),相对第一次接触堆的时候有了较大的提高,手写堆得代码也可以因此变得更为简洁。详细算法参加下面的代码。

        其次是关于快速输入输出(FastIO),我在这里用结构体进行封装,创建对象IO时可以完成构造函数的操作,包括stdin和stdout两个流向,一个是最大400万次输入,一个是最大200万次输出,相信这样可以将输入输出此时降至十位甚至个位数,将输入输出对时间的消耗降至极低的水平。

        简单介绍这里使用的一个设置文件缓存区的函数和另一个相似函数:

        设置文件缓冲区函数
          void setbuf(FILE *stream,char *buf);

          void setvbuf(FILE *stream,char *buf,int type,unsigned size);
          这两个函数将使得打开文件后,用户可建立自己的文件缓冲区,而不使用fopen()函数打开文件设定的默认缓冲区。  

          对于setbuf()函数,buf指出缓冲区长度,由stdio.h中定义的宏BUFSIZE的值决定,缺省为512字节。当buf为空时,setbuf函数将使的文件I/O不带缓冲。

          对setvbuf函数,则由malloc函数来分配缓冲区,参数size指明了缓冲区的长度。

        type则表示了缓冲的类型,其值可以取如下值:

          _IOFBF 文件全部缓冲,即缓冲区装满后,才能对文件读写
          _IOLBF 文件行缓冲,即缓冲区接收到一个换行符时,才能对文件读写

          _IONBF 文件不缓冲,此时忽略buf,size的值,直接读写文件,不再经过文件缓冲区缓冲

      代码的写法模仿了一篇博客,在此表示感谢:terence-yang

      具体代码如下:

      

     1 //优先级队列+快速输入输出(批量)
     2 //Time: 1508Ms Memory: 109488K(No.20)
     3 #include<iostream>
     4 #include<cstdio>
     5 #include<cstring>
     6 using namespace std;
     7 
     8 #define MAX 4000005
     9 #define LCHILD(x) ((x)<<1)
    10 #define RCHILD(x) (((x)<<1) + 1)
    11 #define PRIOR(A,x,y) (A[x]>A[y]?(x):(y))
    12 
    13 int n, m;
    14 const long long INF = (long long)1 << 32;    //优先级数上限
    15 const int SIZE = 1 << 21;        //缓存区大小
    16 
    17 /*快速输入输出缓存区设置*/
    18 struct FastIO {
    19     char inbuf[SIZE];
    20     char outbuf[SIZE];
    21     FastIO() {
    22         setvbuf(stdin,inbuf,_IOFBF,SIZE);
    23         setvbuf(stdout,outbuf,_IOFBF,SIZE);
    24     }
    25 }IO;
    26 
    27 struct Task {
    28     char word[9];
    29     long long v;
    30     bool operator > (Task &a){        /*重载为优先级比较符*/
    31         return v < a.v || v == a.v && strcmp(word, a.word) < 0;
    32     }
    33 }task[MAX];
    34 
    35 /*在parent和child之间找到最高优先级代替parent*/
    36 int replacePa(int x)
    37 {
    38     int pa = x;
    39     if (RCHILD(x) <= n)
    40         pa = PRIOR(task, x, PRIOR(task, LCHILD(x), RCHILD(x)));
    41     else if (LCHILD(x) <= n)
    42         pa = PRIOR(task, x, LCHILD(x));
    43     return pa;
    44 }
    45 
    46 /*下滤(向下调整堆)*/
    47 void percolateDown(int x)
    48 {
    49     int rp = replacePa(x);
    50     while (rp != x) {
    51         swap(task[rp], task[x]);
    52         x = rp;
    53         rp = replacePa(x);
    54     }
    55 }
    56 
    57 /*批量建堆(堆积)*/
    58 void heapify()
    59 {
    60     for (int i = n / 2; i >= 1; i--)
    61         percolateDown(i);
    62 }
    63 
    64 int main()
    65 {
    66     scanf("%d%d", &n, &m);
    67     for (int i = 1; i <= n; i++)
    68         scanf("%lld%s", &task[i].v, task[i].word);
    69     heapify();
    70 
    71     for (int i = 0; n && i < m; i++)
    72     {
    73         printf("%s
    ", task[1].word);
    74         task[1].v *= 2;
    75         if (task[1].v >= INF)
    76             task[1] = task[n--];
    77         percolateDown(1);
    78     }
    79 
    80     return 0;
    81 }
    他坐在湖边,望向天空,她坐在对岸,盯着湖面
  • 相关阅读:
    legend3---图片裁剪实例代码
    JPG 和 JPEG 格式有什么区别
    jpg与png图片的优缺点
    心得体悟帖---200320(legend3它的真实意义,在于资质提升,一举多得)
    心得体悟帖---200320(觉得录课录不下去了,可以去招聘市场找找激励,这个真的特别有效)
    心得体悟帖---200320(我必不甘于人之下,所以还是得自己干,自己好好录课)
    ES6参考---Promise对象
    范仁义js课程---70、sort方法
    JS实现异步编程的4种方法(总结)
    JS执行机制详解
  • 原文地址:https://www.cnblogs.com/Inkblots/p/5093232.html
Copyright © 2020-2023  润新知