思路:
1.使用大小为n的堆,进行模拟计算。
2.通过二分法,找出最优的堆的大小。
3.注意q和其他输入的取值大小。
描述
小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
AC代码:
[c language=”++”]
//#include<string>
//#include <iomanip>
#include<vector>
#include <algorithm>
//#include<stack>
#include<set>
#include<queue>
#include<map>
//#include<unordered_set>
#include<unordered_map>
//#include <sstream>
//#include "func.h"
//#include <list>
#include<stdio.h>
#include<iostream>
#include<string>
#include<memory.h>
#include<limits.h>
#include<bitset>
//#include "siukwanAlloctor.h"
using namespace std;
long long arr[100002] = { 0 };
int size = 0;
long long pop()
{
if (size == 0) return 0;
long long result = arr[0];//获取栈顶元素
long long x = arr[–size];//把队尾元素提到0号位置
arr[size] = 0;
int i = 0;
int a = i * 2 + 1;//左孩子
int b = i * 2 + 2;//右孩子
while (a<size)
{
if (b<size&&arr[a]<arr[b])
a = b;//右孩子比左孩子大
if (x<arr[a])//孩子的值比父亲大,提上来
arr[i] = arr[a];
else//父亲的值比孩子大,停止操作
break;
i = a;
a = i * 2 + 1;
b = a + 1;
}
arr[i] = x;
return result;
}
void push(long long x)
{
int i = size++;
int p = (i – 1) / 2;//父亲节点
while (x>arr[p])
{//孩子节点的值比父亲的值大
arr[i] = arr[p];
i = p;
if (i == 0) break;
p = (i – 1) / 2;
}
arr[i] = x;
}
int main()
{
int n;
long long quality;
int data[100002] = { 0 };
scanf("%d", &n);
scanf("%ld", &quality);
for (int i = 0; i < n; ++i)
{
scanf("%d", &data[i]);
}
long long sum = 0;
int result = -1;
int a = 1;
int b = n;
int mid = (a + b) / 2;
while (a <= b)
{
memset(arr, 0, sizeof(arr));
sum = 0;
mid = (a + b) / 2;
//建立大小为mid的堆
int i = 0;
int j = 1;//权重
for (i = 0; i < mid; ++i)
{
push(data[i]);
}
//一个一个统计
for (; i < n; ++i)
{
long long x = pop();//缓冲区已经满,把头部弹出来
sum += x*(j++);
push(data[i]);
}
while (size != 0)
{
long long x = pop();//缓冲区已经满,把头部弹出来
sum += x*(j++);
}
if (sum <= quality)
b = mid – 1;//尝试更小的空间
else
a = mid + 1;
if (sum <= quality && (result == -1 || mid < result))
result = mid;
}
cout << result << endl;
return 0;
}
[/c]