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;
}

 

 

 

posted on 2012-11-09 20:51  Staginner  阅读(892)  评论(2编辑  收藏  举报