这周的题目比上周更难了,但是在做题过程中也学到了很多新知识。首当其次便是二分法。

看到这里你可能会感到很疑惑,“什么?二分不是初学者都会写吗”。确实,写二分非常简单,但这几道题难就难在你不知道要用二分,不知道怎么用二分。

首先来看第一题,这也是最简单的一题

“本题输入输出量较大,请使用较快的 IO 方式。”这句话直接掐断多少人暴力循环查找的念头。显然,二分查找对这题来说是非常合适的。但是,我又在解决这道题的时候学习到了一个新知识:stl里有自带的二分函数:upper_bound 和 lower_bound 。前者的意思是返回第一个大于搜索数的位置,后者的意思是返回第一个大于等于的数的位置。在这道题中,显然后者更好用一点。

注意!!!返回的是位置!所以肯定要用到数组,并且返回后还得减去数组本身(位置)

下面是题解

#include <bits/stdc++.h>
using namespace std;
int A[1000010],B[1000010];
int main(){int n,m;cin>>n>>m;for(int i=1;i<=n;i++){//注意注意注意,从int从1开始!cin>>A[i];}for(int i1=0;i1<m;i1++){cin>>B[i1];}for(int k=0;k<m;k++){int x=lower_bound(A+1,A+n+1,B[k])-A;//注意注意注意,新知识if(B[k]!=A[x]){cout<<"-1";}if(B[k]==A[x]){cout<<x;}if(k!=m-1){cout<<' ';}}return 0;
}

由于思路简单易懂,注释就不多写了。这里再附上手打二分解法,选用手打二分解法其实对后面的解题更有帮助。

#include <bits/stdc++.h>
using namespace std;
int n,m,q,a[1000005];
int find(int x) //二分查找
{int l=1,r=n;while (l<r){int mid=l+(r-l)/2;if (a[mid]>=x) r=mid;else l=mid+1;}if (a[l]==x)return l; //找对了else return -1; //没找对
}int main()
{cin>>m>>n; for (int i=1 ; i<=n ; i++)cin>>a[i];   for (int i=1 ; i<=m ; i++){cin>>q;int ans=find(q); //看看查找的结果 cout<<ans; }return 0;
}

接下来就是第二题了,先看题

这道题说实话,我一开始就没想到用二分,甚至在知道要用二分解的时候还疑惑了很久。最终本蒟蒻在反复观摩来自洛谷的Accele_Rator大佬的详细解读后才明白这题要怎么使用二分。

对大佬的代码做了一些修改,现在可能更好读一点

#include <bits/stdc++.h>
using namespace std;
int A[1000010];
int n,c,a;
bool check(int x) //bool判断(本题最核心思路)
{int num=0;int l=A[1]; for(int i=2;i<=n;i++){if(A[i]-l<x) num++; //若此距离不满足当前答案,那么需要的牛栏数+1,即把当前牛放到下一个牛栏 else l=A[i]; //否则就更新上一次的牛栏位置 ,即上一头牛放的位置 if(num>a) return false; //若需要牛栏数大于最大牛栏数,此答案不可行 }return true; //反之,若需要牛栏数小于最大需要牛栏数,此答案可行
}
int main()
{ cin>>n>>c;for(int i=1;i<=n;i++){cin>>A[i] ;}sort(A+1,A+n+1); //排序a=n-c; //最大剩余牛栏数 int l=1; //一定为最小int r=A[n]-A[1]; //一定为最大 while(l+1<r) //若左<右,则继续二分答案 {int mid=(l+r)/2; //二分两区间分别为l ~ mid,mid ~ r;if(check(mid))l=mid; //若此答案可行,从mid ~ r区间继续查找(更大答案),即修改左界l=mid else r=mid; //反之,若此答案不可行,从l ~ mid区间查找(合理答案),即修改左界l=mid }if(check(r)) cout<<r ;//若可行解为右界,输出右界 else cout<<l ;//若可行解为左界,输出左界 return 0;
}

可以发现,这道题的核心判断点就在于二分的结果与牛栏跨度大小的比较。思路已经很难想了,能够写出来更不简单,笔者在这里再次对大佬表示膜拜。

然后便是最后一题了,先看题

这道题在第二题难度的基础上更进一步。我也通过这道题学习了两个新知识:位运算加速以及贪心算法。这题用到位运算加速中的>>n,其含义为“>>”左边的数的二进制形式往右移动n位。比如4>>1,意思就是3的二进制形式0100右移一位变成0010,运算结果为2。而贪心算法由于内容比较多,其中更有许多我不甚了解的细枝末节,我就不详细赘述了。想对贪心算法进行了解的读者点击下面链接即可。这道题采用的便是贪心算法的局部最优化的想法。

(14条消息) 贪心算法(贪婪算法)_一个软泥怪的博客-CSDN博客_贪心算法

题解:

#include <bits/stdc++.h>
using namespace std;
int sto[100000];//开大一点,保险
int main()
{int s,n,m;cin>>s>>n>>m;int zuo=1,you=s,mid;//所有边界为1、sfor(int i=0;i<n;i++)cin>>sto[i];sort(sto,sto+n);//从小到大排序int sg,cnt,ii;while(zuo!=you){mid=(zuo+you+1)>>1;//位运算加速sg=cnt=0;//初始化for(ii=0;ii<n;ii++){if(s-sto[ii]<mid)break; //如解析中所述,若再跳x已超过终点,则不可取此点,它后面的也显然不可取if(sto[ii]-sg<mid)cnt++; //跳过else sg=sto[ii]; //贪心,直接跳到}cnt+=n-ii;//统计最后被删除的点数if(cnt<=m)zuo=mid;else you=mid-1;//二分边界更新,具体请见解析}cout<<zuo;return 0;
}

本周的学习就到此结束了。很抱歉,由于这周(其实是已经上周了)学校的事情太多,作者没能实现一周一更的承诺,这篇博客写的也挺匆忙。这周一定按时发布课业博客,望读者大大海涵。

week 2 二分主场相关推荐

  1. 算法图解/二分查找/简单查找/选择排序/递归算法/快速排序算法/

    大 O 表示法 大 O 表示法在讨论运行时间时,log 指的都是 log2 大 O 表示法指出了算法有多快,让你能够比较操作数,它指出了算法运行时间的增速,而并非以秒为单位的速度. 大 O 表示法指出 ...

  2. 分治算法的设计思想(二分检索、二分归并排序)

    分治策略思想: 将原问题划分或者归结为规模较小的子问题. 递归或迭代求解每一个问题. 将子问题的解综合得到原问题的解. 性质: 子问题与原问题具有相同的性质. 子问题的求解彼此独立. 划分时子问题的规 ...

  3. LeetCode简单题之二分查找

    题目 给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1. 示例 1: 输入: n ...

  4. 二分查找模板全面总结

    二分查找 二分法的引入 情形1 1.X的平方根 2.搜索旋转排序数组 情形2 1.第一个错误的版本 2.寻找峰值 3.寻找旋转排序数组中的最小值 情形3 在排序数组中查找第一个和最后一个位置 当遇到查 ...

  5. [C] [二分] C语言实现快速排序

    为了以防万一有人想不开想手撕快排呢?比如我. 通过快排来理解二分思想 什么是快排? 快排的思想不难,理解好递归很重要. 什么是递归? 递归,就是在运行的过程中调用自己. 构成递归需具备的条件: 子问题 ...

  6. Showstopper [POJ3484] [二分] [思维]

    Description 给你n个数列,问哪一个数字在所有的数列中出现了奇数次(最多一个). Sample Input 1 10 1 2 10 11 10 1 1 10 11 10 1 4 4 1 1 ...

  7. BZOJ3166 [Heoi2013]Alo 【可持久化trie树 + 二分 + ST表】

    题目 Welcome to ALO ( Arithmetic and Logistic Online).这是一个VR MMORPG , 如名字所见,到处充满了数学的谜题. 现在你拥有n颗宝石,每颗宝石 ...

  8. usaco The Perfect Stall(二分匹配模板)

    其实二分匹配都是很早之前看的不过又忘了现在再看看比第一次好理解多了. /* ID:jinbo wu TASK:stall4 LANG:C++ */ #include<bits/stdc++.h& ...

  9. php二分搜索,php如何实现二分搜索法

    在php中实现二分搜索法的方法:首先,取数组中的一个值作为边界:然后递归搜索直到最后,代码是[if ($ low 本教程的操作环境:windows7系统,PHP 5.6版,DELL G3电脑.此方法适 ...

最新文章

  1. jQuery学习---------认识事件处理
  2. tc溜溜865手机投屏卡_这台手机智商为零,却要挑战小米华为!
  3. 第一周 01-复杂度2 Maximum Subsequence Sum
  4. C++编程风格(一)
  5. 【Tiny4412】烧写最小文件系统到EMMC
  6. (转)Apache与Tomcat 区别联系
  7. upload-labs_less3_less4_等价扩展名绕过_.htaccess文件改变文件扩展名
  8. mysql-5.7.10-winx64 MySQL服务无法启动,服务没有报告任何错误的解决办法
  9. PAT 1009 说反话
  10. webstorm编辑器的一些快捷键的用法
  11. fopen后面参数对文件操作的相应关系
  12. Eucalyptus EE的介绍及功能说明
  13. pkill mysql_MYSQL之mysqlcheck命令
  14. 关于长城!你可能不知道......
  15. 使用TimerOne库
  16. JDK11源码学习05 | HashMap类
  17. 百度Apollo自动驾驶_百度车载小程序
  18. 软件测试前景怎么样?大概要学什么?
  19. Python正则表达式用法详解
  20. 发送writely和orkut邀请

热门文章

  1. 【我的前端】前端项目小练习:CSS创建3D圆柱旋转效果
  2. PHP中间件 middleware,middleware 中间件详解
  3. base64转file文件(两种方法)
  4. Win10开启FTP与配置(完整无错版)
  5. #systemverilog# “类”翱翔在systemverilog的天空(2)常用类型举例
  6. 计算机视觉Computer Vision领域博客资源
  7. 回忆那些楼市成交的黄金岁月(全)
  8. 深入学习Lua知识点整理
  9. python入门基础语法
  10. python上机实验报告心得体会_Python开发实习心得~