LOJ #2141. 「SHOI2017」期末考試
阿新 • • 發佈:2018-02-12
for string 學生 pla get read 三分 sort 為什麽
題目鏈接
LOJ #2141
題解
據說這道題可以三分(甚至二分)?
反正我是枚舉的 = =
先將t和b數組排序後計算出前綴和,
然後枚舉最晚的出成績時間,每次可以O(1)直接計算調整到該時間所需的代價。
如何計算?
對於學生不滿意造成的代價,是 (不滿意人數 * 最晚結束時間) - 所有不滿的人的t之和;
對於調整老師造成的代價, A < B 時先用A調整 (可用前綴和計算出有多少時間能用來交換,又有多少時間需要被交換)再用B調整仍超出的部分; 否則都用B調整。
真的如高大佬所言是sb題啊 = =
為什麽當年的我不會啊
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <cstdlib>
#define space putchar(' ')
#define enter putchar('\n')
using namespace std;
typedef unsigned long long ll;
template <class T>
void read(T &x){
char c;
bool op = 0;
while (c = getchar(), c < '0' || c > '9')
if(c == '-') op = 1;
x = c - '0';
while(c = getchar(), c >= '0' && c <= '9')
x = x * 10 + c - '0';
if(op) x = -x;
}
template <class T>
void write(T x){
if(x < 0) putchar('-' ), x = -x;
if(x >= 10) write(x / 10);
putchar('0' + x % 10);
}
const int N = 100005;
ll n, m, A, B, C, t[N], sumt[N], b[N], sumb[N], tim, ans = 1LL << 62;
int main(){
read(A), read(B), read(C);
read(n), read(m);
for(ll i = 1; i <= n; i++) read(t[i]);
sort(t + 1, t + n + 1);
for(ll i = 1; i <= n; i++) sumt[i] = sumt[i - 1] + t[i];
for(ll i = 1; i <= m; i++) read(b[i]);
sort(b + 1, b + m + 1);
for(ll i = 1; i <= m; i++) sumb[i] = sumb[i - 1] + b[i];
ll pt = 0, pb = 0;
for(tim = 0; tim <= b[m]; tim++){
while(pt < n && t[pt + 1] < tim) pt++;
while(pb < m && b[pb + 1] < tim) pb++;
ll sumbl = pb * tim - sumb[pb], sumbr = sumb[m] - sumb[pb] - (m - pb) * tim;
ll res = min(sumbr * B, min(sumbl, sumbr) * A + (sumbr - min(sumbl, sumbr)) * B);
res += (pt * tim - sumt[pt]) * C;
ans = min(ans, res);
}
write(ans), enter;
return 0;
}
LOJ #2141. 「SHOI2017」期末考試