BZOJ4985 評分 二分答案、DP
阿新 • • 發佈:2018-10-31
過程 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