1. 程式人生 > >LOJ #2141. 「SHOI2017」期末考試

LOJ #2141. 「SHOI2017」期末考試

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」期末考試