BZOJ4985 评分 二分答案、DP

时间:2021-03-05 00:35:10

传送门

题意:自己去看


答案满足单调性,所以考虑二分答案。

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

考虑DP:设$f_i$表示队列中第$i$个人的分数$\geq \, mid$的代价,最开始$N$个人的代价显然是:如果当前位置上没有人为$1$,如果当前的人分数$\geq mid$为$0$,否则为$INF$。$N+1$到$ans$的转移就是当前队伍的前$3$个人中至少有两个人$\geq \, mid$的代价的最小值,用队列模拟DP过程即可。

 //This code is written by Itst
 #define INF 0x3f3f3f3f
 #include<bits/stdc++.h>
 using namespace std;

 inline int read(){
     ;
     ;
     char c = getchar();
     while(c != EOF && !isdigit(c)){
         if(c == '-')
             f = ;
         c = getchar();
     }
     while(c != EOF && isdigit(c)){
         a = (a << ) + (a << ) + (c ^ ');
         c = getchar();
     }
     return f ? -a : a;
 }

 ;
 int pri[MAXN] , notin[MAXN] , N , M;
 queue < int > q;

 bool check(int mid){
      ; i <= N ; i++)
         if(!pri[i])
             q.push();
         else
             q.push(pri[i] >= mid ?  : INF);
      - (lower_bound(notin +  , notin + N - M +  , mid) - notin);
     ){
         int t = q.front();
         q.pop();
         if(q.empty())
             return t <= num;
         long long p = q.front();
         q.pop();
         long long r = q.front();
         q.pop();
         ))
             q.push(INF);
         else
             q.push(min(t + p , min(p + r , t + r)));
     }
 } 

 int main(){
 #ifdef BZ
     freopen("4985.in" , "r" , stdin);
     //freopen("4985.out" , "w" , stdout);
 #endif
     N = read();
     M = read();
      ; i <= M ; i++){
         int a = read() , b = read();
         pri[b] = a;
     }
      ; i <= N - M ; i++)
         notin[i] = read();
     sort(notin +  , notin + N - M + );
      , R = 1e9;
     while(L < R){
          >> ;
         check(mid) ? L = mid : R = mid - ;
     }
     cout << L;
     ;
 }