题目1 : 优化延迟
描述
小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 385 3 1 2 4
样例输出 -
2
题目链接:
题目非常明显就是裸的二分答案,想测试的堆看看手写的是不是有问题,以及速度如何,比封装的pq要快一些前者700ms+后者1000ms+,方便起见我的堆是递归形式的,非递归就不是很熟了。
代码:
#include#include 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 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\n", ans); } return 0;}