1. 程式人生 > >BZOJ4985 評分 二分答案、DP

BZOJ4985 評分 二分答案、DP

過程 fine tle zoj define 隊列 最小值 read $1

傳送門

題意:自己去看


答案滿足單調性,所以考慮二分答案。

二分答案很好想,但是check並不是很好想。

考慮DP:設$f_i$表示隊列中第$i$個人的分數$\geq \, mid$的代價,最開始$N$個人的代價顯然是:如果當前位置上沒有人為$1$,如果當前的人分數$\geq mid$為$0$,否則為$INF$。$N+1$到$ans$的轉移就是當前隊伍的前$3$個人中至少有兩個人$\geq \, mid$的代價的最小值,用隊列模擬DP過程即可。

 1 //This code is written by Itst
 2 #define INF 0x3f3f3f3f
 3 #include<bits/stdc++.h>
 4
using namespace std; 5 6 inline int read(){ 7 int a = 0; 8 bool f = 0; 9 char c = getchar(); 10 while(c != EOF && !isdigit(c)){ 11 if(c == -) 12 f = 1; 13 c = getchar(); 14 } 15 while(c != EOF && isdigit(c)){ 16 a = (a << 3
) + (a << 1) + (c ^ 0); 17 c = getchar(); 18 } 19 return f ? -a : a; 20 } 21 22 const int MAXN = 100000; 23 int pri[MAXN] , notin[MAXN] , N , M; 24 queue < int > q; 25 26 bool check(int mid){ 27 for(int i = 1 ; i <= N ; i++) 28 if(!pri[i]) 29 q.push(1
); 30 else 31 q.push(pri[i] >= mid ? 0 : INF); 32 int num = N - M + 1 - (lower_bound(notin + 1 , notin + N - M + 1 , mid) - notin); 33 while(1){ 34 int t = q.front(); 35 q.pop(); 36 if(q.empty()) 37 return t <= num; 38 long long p = q.front(); 39 q.pop(); 40 long long r = q.front(); 41 q.pop(); 42 if(p + r + t >= (INF << 1)) 43 q.push(INF); 44 else 45 q.push(min(t + p , min(p + r , t + r))); 46 } 47 } 48 49 int main(){ 50 #ifdef BZ 51 freopen("4985.in" , "r" , stdin); 52 //freopen("4985.out" , "w" , stdout); 53 #endif 54 N = read(); 55 M = read(); 56 for(int i = 1 ; i <= M ; i++){ 57 int a = read() , b = read(); 58 pri[b] = a; 59 } 60 for(int i = 1 ; i <= N - M ; i++) 61 notin[i] = read(); 62 sort(notin + 1 , notin + N - M + 1); 63 int L = 0 , R = 1e9; 64 while(L < R){ 65 int mid = L + R + 1 >> 1; 66 check(mid) ? L = mid : R = mid - 1; 67 } 68 cout << L; 69 return 0; 70 } 71

BZOJ4985 評分 二分答案、DP