• LA 4254 Processor


    LA_4254

        一般最大值最小的问题都可以通过二分来求解,这个题目也不例外。我们对处理器速度进行二分之后,问题就转化成了对于给定的处理速度,问处理器是否可以将这些问题处理完。一个贪心的思路就是每个时刻应该尽量做可以做的任务中,结束时间最早的那个,这样最起码不会使结果更糟。这样就可以枚举每个单位时间,然后去找可以做的并且结束时间最早的那个去做,直到用完这一单位时间或者无任务可做为止。最后如果发现哪个任务还没做完,就说明在这个给定的处理速度下,处理器是不能完成所有任务的。

        在查找结束时间最早的可做的任务的过程中,我的代码借助了线段树。不过据AC排名来看,应该还有更简便的算法,只不过我暂时没有想到。

    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #include<iostream>
    #define MAXN 10010
    #define INF 0x3f3f3f3f
    typedef long long LL;
    int N, D, tree[4 * MAXN], di[2 * MAXN], remain[MAXN];
    struct A
    {
        int r, d, w;
    }a[MAXN];
    bool cmp(const int x, const int y)
    {
        int tx = x > 0 ? a[x].r : a[-x].d, ty = y > 0 ? a[y].r : a[-y].d;
        return tx < ty;
    }
    void input()
    {
        scanf("%d", &N);
        for(int i = 1; i <= N; i ++)
        {
            scanf("%d%d%d", &a[i].r, &a[i].d, &a[i].w);
            di[2 * i - 2] = i, di[2 * i - 1] = -i;
        }
        std::sort(di, di + 2 * N, cmp);
        for(D = 1; D < N + 2; D <<= 1);
        memset(tree, 0, sizeof(tree[0]) * 2 * D);
        a[0].d = INF;
    }
    void update(int i)
    {
        for(; i ^ 1; i >>= 1) tree[i >> 1] = a[tree[i]].d < a[tree[i ^ 1]].d ? tree[i] : tree[i ^ 1];
    }
    int gett(int i)
    {
        return i > 0 ? a[i].r : a[-i].d;
    }
    int can(int m)
    {
        for(int i = 1; i <= N; i ++) remain[i] = a[i].w;
        di[2 * N] = di[2 * N - 1];
        for(int i = 0; i < 2 * N; i ++)
        {
            if(di[i] > 0) tree[D + di[i]] = di[i], update(D + di[i]);
            else tree[D - di[i]] = 0, update(D - di[i]);
            LL use = (LL)m * (gett(di[i + 1]) - gett(di[i]));
            while(use)
            {
                int id = tree[1];
                if(id == 0) break;
                if(use >= remain[id])
                {
                    use -= remain[id], remain[id] = 0;
                    tree[D + id] = 0, update(D + id);
                }
                else remain[id] -= use, use = 0;
            }
        }
        for(int i = 1; i <= N; i ++) if(remain[i]) return 0;
        return 1;
    }
    void process()
    {
        int min = 0, max = 10000010, mid;
        for(;;)
        {
            mid = (max - min) / 2 + min;
            if(mid == min) break;
            if(can(mid)) max = mid;
            else min = mid;
        }
        std::cout << mid + 1 << std::endl;
    }
    int main()
    {
        int t;
        scanf("%d", &t);
        while(t --)
        {
            input();
            process();
        }
        return 0;
    }
  • 相关阅读:
    依次逐个亮灯并且每次只能亮一个灯的跑马灯程序
    逐个点亮LED灯,再逐个熄灭LED灯的跑马灯程序---基于74HC595移位锁存器,程序框架用switch语句
    把74HC595驱动程序翻译成类似单片机IO口直接驱动的方式
    两片联级74HC595驱动16个LED灯的基本驱动程序
    树莓派
    Linux I2C驱动
    转:使用 /proc 文件系统来访问 Linux 内核的内容
    转: 使用 /sys 文件系统访问 Linux 内核
    树梅派 -- 通过/sys读写ADC芯片 pcf8591
    树莓派 -- oled 续(2) python
  • 原文地址:https://www.cnblogs.com/staginner/p/2763246.html
Copyright © 2020-2023  润新知