51nod1279(二分)

Posted ygeloutingyu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了51nod1279(二分)相关的知识,希望对你有一定的参考价值。

题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1279

 

题意:中文题诶~

 

思路:

就想短板效应一样,很显然决定当前盘子能否到达高度x位置的是井口到x位置的最窄地方能否放下盘子,那么我们可以用 vis[i]存储井口到深度为i的位置的最窄宽度,那么显然vis数组是降序排列的。

遍历所有盘子,对于当前盘子,我们可以用二分查找vis数组中的最大下界,假设其为pos, 那么当前盘子会落在pos-1位置;

那么在下一轮查找中,查找范围为 0~pos-2。

直至遍历完所有盘子或者井满了或者出现了一个超级大盘子把井盖住了。

 

代码:

 1 #include <bits/stdc++.h>
 2 #define MAXN 50010
 3 using namespace std;
 4 
 5 const int inf=1e9;
 6 int a[MAXN], b[MAXN], vis[MAXN];
 7 
 8 int dichotomous(int key, int h){ //***查找最大下界
 9     int l=0, r=h, mid=(l+h)>>1;
10     if(key>vis[0]){
11         return 0;
12     }
13     if(key<=vis[h]){
14         return -1;
15     }
16     while(l<r){
17         if(vis[mid]<key&&vis[mid-1]>=key){
18             return mid;
19         }
20         if(vis[mid]>=key){
21         }else{
22             l=mid+1;
23             r=mid-1;
24         }
25         mid=(l+r)>>1;
26     }
27     return mid;
28 }
29 
30 int main(void){
31     int h, m, cc=inf;
32     scanf("%d%d", &h, &m);
33     for(int i=0; i<h; i++){
34         scanf("%d", &a[i]);
35         cc=min(cc, a[i]);
36         vis[i]=cc;
37     }
38     for(int i=0; i<m; i++){
39         scanf("%d", &b[i]);
40     }
41     int ans=0, k=0, gg=h-1;
42     while(gg>=0&&k<m){
43         int pos=dichotomous(b[k++], gg);
44         if(pos==-1){ //***当前盘子落到上一个盘子上
45             gg--;
46             ans++;
47         }else if(pos==0){ //***盘子把井盖住了
48             break;
49         }else{ //***盘子卡在井里面
50             gg=pos-2;
51             ans++;
52         }
53     }
54     cout << ans << endl;
55     return 0;
56 }

 

对于降序数组不能用lower_bound(),当然本题可以把vis写成升序的。我感觉好久没手撸二分了所以手撸的二分,果然隔太久没写会不熟练。

以上是关于51nod1279(二分)的主要内容,如果未能解决你的问题,请参考以下文章

51nod 1279 单调栈

51nod 1279单调栈扔盘子

51Nod 1279

51nod 1279 扔盘子

51 nod 1279 扔盘子

51Nod 1279 扔盘子