hihoCoder 第136周 优化延迟(二分答案+手写堆)

题目1 : 优化延迟

时间限制:10000ms
单点时限:1000ms
内存限制:256MB

描述

小Ho编写了一个处理数据包的程序。程序的输入是一个包含N个数据包的序列。每个数据包根据其重要程度不同,具有不同的"延迟惩罚值"。序列中的第i个数据包的"延迟惩罚值"是Pi。如果N个数据包按照<Pi1, Pi2, ... PiN>的顺序被处理,那么总延迟惩罚

SP=1*Pi1+2*Pi2+3*Pi3+...+N*PiN(其中i1, i2, ... iN是1, 2, 3, ... N的一个排列)。

小Ho的程序会依次处理每一个数据包,这时N个数据包的总延迟惩罚值SP为

1*P1+2*P2+3*P3+...+i*Pi+...+N*PN。  

小Hi希望可以降低总延迟惩罚值。他的做法是在小Ho的程序中增加一个大小为K的缓冲区。N个数据包在被处理前会依次进入缓冲区。当缓冲区满的时候会将当前缓冲区内"延迟惩罚值"最大的数据包移出缓冲区并进行处理。直到没有新的数据包进入缓冲区时,缓冲区内剩余的数据包会按照"延迟惩罚值"从大到小的顺序被依次移出并进行处理。

例如,当数据包的"延迟惩罚值"依次是<5, 3, 1, 2, 4>,缓冲区大小K=2时,数据包被处理的顺序是:<5, 3, 2, 4, 1>。这时SP=1*5+2*3+3*2+4*4+5*1=38。

现在给定输入的数据包序列,以及一个总延迟惩罚阈值Q。小Hi想知道如果要SP<=Q,缓冲区的大小最小是多少?

输入

Line 1: N Q

Line 2: P1 P2 ... PN

对于50%的数据: 1 <= N <= 1000

对于100%的数据: 1 <= N <= 100000, 0 <= Pi <= 1000, 1 <= Q <= 1013

输出

输出最小的正整数K值能满足SP<=Q。如果没有符合条件的K,输出-1。

样例输入
5 38
5 3 1 2 4
样例输出
2

题目链接:hihoCoder 第136周

题目非常明显就是裸的二分答案,想测试的堆看看手写的是不是有问题,以及速度如何,比封装的pq要快一些前者700ms+后者1000ms+,方便起见我的堆是递归形式的,非递归就不是很熟了。

代码:

#include <stdio.h>
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define LC(x) (x<<1)
#define RC(x) ((x<<1)+1)
#define MID(x,y) ((x+y)>>1)
#define CLR(arr,val) memset(arr,val,sizeof(arr))
#define FAST_IO ios::sync_with_stdio(false);cin.tie(0);
typedef pair<int, int> pii;
typedef long long LL;
const double PI = acos(-1.0);
const int N = 100010;
LL arr[N];
int n;
LL q;

struct heap
{
    LL a[N];
    int sz;
    void init()
    {
        sz = 0;
    }
    void up(const int &cur)
    {
        int fa = cur >> 1;
        if (fa > 0 && a[cur] > a[fa])
        {
            swap(a[cur], a[fa]);
            up(fa);
        }
    }
    void down(const int &cur)
    {
        int lson = cur << 1, rson = cur << 1 | 1;
        if (lson > sz)
            return ;
        else
        {
            int tar;
            if (rson > sz)
                tar = lson;
            else
                tar = a[lson] > a[rson] ? lson : rson;
            if (a[cur] < a[tar])
            {
                swap(a[tar], a[cur]);
                down(tar);
            }
        }
    }
    void push(int x)
    {
        a[++sz] = x;
        up(sz);
    }
    void pop()
    {
        swap(a[sz--], a[1]);
        down(1);
    }
    LL top()
    {
        return a[1];
    }
    bool empty()
    {
        return !sz;
    }
};
heap one;

bool check(const int &k)
{
    one.init();
    LL bas = 1LL;
    LL sp = 0LL;
    for (int i = 1; i <= k; ++i)
        one.push(arr[i]);
    for (int i = k + 1; i <= n; ++i)
    {
        sp += (bas++) * one.top();
        one.pop();
        one.push(arr[i]);
    }
    while (!one.empty())
    {
        sp += (bas++) * one.top();
        one.pop();
    }
    return sp <= q;
}
int main(void)
{
    int i;
    while (~scanf("%d%lld", &n, &q))
    {
        for (i = 1; i <= n; ++i)
            scanf("%lld", arr + i);
        int ans = -1;
        int L = 1, R = n;
        while (L <= R)
        {
            int mid = (L + R) >> 1;
            if (check(mid))
            {
                R = mid - 1;
                ans = mid;
            }
            else
                L = mid + 1;
        }
        printf("%d
", ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/Blackops/p/6370087.html