【bzoj4868】[Shoi2017]期末考試 前綴和
阿新 • • 發佈:2017-07-03
[1] con microsoft pre log mic 表示 div 描述
第一行三個非負整數A,B,C,描述三種不愉快度,詳見【問題描述】;
第二行兩個正整數n,m(1≤n,m≤105),分別表示學生的數量和課程的數量;
第三行n個正整數ti,表示每個學生希望的公布成績的時間;
第四行m個正整數bi,表示按照原本的計劃,每門課程公布成績的時間。
1<=N,M,Ti,Bi<=100000,0<=A,B,C<=100000
題目描述
有n位同學,每位同學都參加了全部的m門課程的期末考試,都在焦急的等待成績的公布。第i位同學希望在第ti天或之前得知所.有.課程的成績。如果在第ti天,有至少一門課程的成績沒有公布,他就會等待最後公布成績的課程公布成績,每等待一天就會產生C不愉快度。對於第i門課程,按照原本的計劃,會在第bi天公布成績。有如下兩種操作可以調整公布成績的時間:1.將負責課程X的部分老師調整到課程Y,調整之後公布課程X成績的時間推遲一天,公布課程Y成績的時間提前一天;每次操作產生A不愉快度。2.增加一部分老師負責學科Z,這將導致學科Z的出成績時間提前一天;每次操作產生B不愉快度。上面兩種操作中的參數X,Y,Z均可任意指定,每種操作均可以執行多次,每次執行時都可以重新指定參數。現在希望你通過合理的操作,使得最後總的不愉快度之和最小,輸出最小的不愉快度之和即可輸入
輸出
輸出一行一個整數,表示最小的不愉快度之和。樣例輸入
100 100 2
4 5
5 1 2 3
1 1 2 3 3
樣例輸出
6
題解
啥數據結構都沒有的sb題
我TM考場上這道sb題才拿了60分真TM喪心病狂。
讀懂題之後大概是NOIP普及組小學生都會。
直接枚舉最終時間,求出同學的不愉快度,然後根據A和B的大小關系決定是否應該調整,以及應該調整多少。使用一個前綴和維護時間和,並用兩個指針維護第一個大於當前時間的等待時間和公布時間。
代碼一點也不難,時間復雜度是$O(n)$的。
另外bzoj中說的$C=10^{18}$有誤,應為$10^{16}$。
#include <cstdio> #include <cstring> #include <algorithm> #define N 100010 using namespace std; typedef long long ll; ll x[N] , y[N] , sx[N] , sy[N]; int main() { ll n , m , i , j , k , a , b , c , ans = 1ll << 62 , s1 , s2 , c1 , c2 , r = 0; scanf("%lld%lld%lld%lld%lld" , &a , &b , &c , &n , &m); for(i = 1 ; i <= n ; i ++ ) scanf("%lld" , &x[i]) , r = max(r , x[i]); for(i = 1 ; i <= m ; i ++ ) scanf("%lld" , &y[i]) , r = max(r , y[i]); sort(x + 1 , x + n + 1) , sort(y + 1 , y + m + 1); for(i = 1 ; i <= n ; i ++ ) sx[i] = sx[i - 1] + x[i]; for(i = 1 ; i <= m ; i ++ ) sy[i] = sy[i - 1] + y[i]; if(c >= 0x7fffffff) r = x[1]; for(i = 1 , j = k = 0 ; i <= r ; i ++ ) { while(j < n && x[j + 1] < i) j ++ ; while(k < m && y[k + 1] < i) k ++ ; s1 = i * k - sy[k] , s2 = sy[m] - sy[k] - i * (m - k) , c1 = c * (i * j - sx[j]); if(a >= b) c2 = s2 * b; else if(s1 >= s2) c2 = s2 * a; else c2 = s1 * a + (s2 - s1) * b; ans = min(ans , c1 + c2); } printf("%lld\n" , ans); return 0; }
【bzoj4868】[Shoi2017]期末考試 前綴和