当前位置: 首页 > wzjs >正文

抚州北京网站建设网络推广营销方法

抚州北京网站建设,网络推广营销方法,wordpress phpstorm,做法城乡建设部网站目录 一、⼆分查找例题 1 牛可乐和魔法封印 2 A-B 数对 3 烦恼的高考志愿 二、 ⼆分答案 1 木材加⼯ 2 砍树 3 跳石头 ⼆分算法的原理以及模板其实是很简单的,主要的难点在于问题中的各种各样的细节问题。因此,⼤多数情况下,只是背会…

目录

一、⼆分查找例题

1 牛可乐和魔法封印

2 A-B 数对

3 烦恼的高考志愿

二、 ⼆分答案

1 木材加⼯

2 砍树

3 跳石头


⼆分算法的原理以及模板其实是很简单的,主要的难点在于问题中的各种各样的细节问题。因此,⼤多数情况下,只是背会⼆分模板并不能解决题目,还要去处理各种乱七⼋糟的边界问题。

【案例】

题⽬来源: ⼒扣

题⽬链接: 34. 在排序数组中查找元素的第⼀个和最后⼀个位置

难度系数: ★★

【题⽬描述】

给你⼀个按照⾮递减顺序排列的整数数组 nums ,和⼀个⽬标值 target 。请你找出给定⽬标值

在数组中的开始位置和结束位置。

如果数组中不存在⽬标值 target ,返回 [-1, -1] 。

你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题

【解法】

解法一:暴力解法->从前往后扫描数组(慢在没有利用数组有序的特征)

解法二:二分算法

解决时的细节问题(因题目而异):

1.while循环里面的判断如何写:while(left <right)/while(left <=right);

2.求中点的方法:(left + right)/2 / (left + right+1)/2;

3.二分结束后,相遇点的情况:需要判断一下,循环结束后,是否是我们想要的结果;

class Solution {
public:vector<int> searchRange(vector<int>& nums, int target) {int n = nums.size();//处理边界情况if(n == 0) return {-1,-1};//1.求起始位置int left = 0,right = n - 1;while(left < right){int mid = (left + right) / 2;if(nums[mid] >= target) right = mid;else left = mid + 1;}if(nums[left] != target) return{-1,-1};int retleft = left;//2.求终止位置left = 0,right = n-1;while(left < right){int mid = (left + right + 1) / 2;if(nums[mid] <= target) left = mid;else right = mid - 1;}return {retleft,left};}
};

【算法原理】

当我们的解具有⼆段性时,就可以使⽤⼆分算法找出答案:

  • 根据待查找区间的中点位置,分析答案会出现在哪⼀侧;
  • 接下来舍弃⼀半的待查找区间,转⽽在有答案的区间内继续使⽤⼆分算法查找结果

【模板】

⼆分的模板在⽹上⾄少能搜出来三个以上。但是,我们仅需掌握⼀个,并且⼀直使⽤下去即可。

// ⼆分查找区间左端点
int l = 1, r = n;
while(l < r)
{int mid = (l + r) / 2;if(check(mid)) r = mid;else l = mid + 1;
}
// ⼆分结束之后可能需要判断是否存在结果
/ ⼆分查找区间右端点
int l = 1, r = n;
while(l < r)
{int mid = (l + r + 1) / 2;if(check(mid)) l = mid;else r = mid - 1;
}
// ⼆分结束之后可能需要判断是否存在结果

 为了防止溢出,求中点时可以使用:mid = left + (right - left) / 2

【⼆分问题解决流程】

1. 先画图分析,确定使⽤左端点模板还是右端点模板,还是两者配合⼀起使⽤;

2. ⼆分出结果之后,不要忘记判断结果是否存在,⼆分问题细节众多,⼀定要分析全⾯。

【STL 中的⼆分查找】

<algorithm>

1. lower_bound :⼤于等于 x 的最⼩元素,返回的是迭代器;时间复杂度: O(log N) 。

2. upper_bound :⼤于 x 的最⼩元素,返回的是迭代器。时间复杂度: O(log N) 。

⼆者均采⽤⼆分实现。但是 STL 中的⼆分查找只能适⽤于"在有序的数组中查找",如果是⼆分答案就不能使⽤。因此还是需要记忆⼆分模板

一、⼆分查找例题

1 牛可乐和魔法封印

题⽬来源: ⽜客⽹

题⽬链接: ⽜可乐和魔法封印

难度系数: ★★

【解法】

解法一:暴力解法->从前往后扫描一遍(O(n*q))

解法二:二分算法

1.找到大于等于x的起始位置

2.找到小于等于y的终止位置

【参考代码】

#include<iostream>
using namespace std;
const int N = 1e5;
int a[N];
int n,q;
int main()
{cin >> n;for(int i = 1;i <= n;i++) cin >> a[i];cin >> q;while(q--){int x,y;cin >> x >> y;//大于等于x的最小元素int left = 1,right = n;while(left < right){int mid = (left + right) / 2;if(a[mid] >= x) right = mid;else left = mid + 1;}if(a[left] < x){cout << 0 << endl;continue;}int retleft = left;//小于等于y的最大元素left = 1,right = n;while(left < right){int mid = (left + right + 1) / 2;if(a[mid] <= y) left = mid;else right = mid - 1;}if(a[left] > y){cout << 0 << endl;continue;}cout << left - retleft + 1 << endl;}return 0;
}

    2 A-B 数对

    题⽬来源: 洛⾕

    题⽬链接:A-B 数对

    难度系数: ★

     【解法】

    分析可得到:

    性质一:元素的顺序是不影响最终结果的

    1. 可以先把整个数组排序
    2. 把A-B=C变形成B=A-C通过枚举A,然后查找有多少个B

    【参考代码】

    #include<iostream>
    #include<algorithm>
    using namespace std;typedef long long LL;
    const int N = 2e5 + 10;
    LL a[N];
    LL n,c;int main()
    {cin >> n >> c;for(int i = 1;i <= n;i++)cin >> a[i];sort(a+1,a+n+1);LL ret = 0;for(int i = 2;i <=n;i++){LL b = a[i] - c;ret += upper_bound(a+1,a+i,b) - lower_bound(a+1,a+i,b);}cout << ret << endl;return 0;
    }
    //其实此题的最优解是哈希表 题解如下:
    // #include<iostream>
    // #include<unordered_map>
    // using namespace std;// const int N = 2e5 + 10;
    // typedef long long LL;
    // LL a[N];
    // unordered_map<LL,LL> mp;
    // LL sum;
    // int main(){
    // 	LL n,c;cin >> n >> c;
    // 	for(LL i = 1;i <= n;i++){
    // 		cin >> a[i];
    // 		mp[a[i]]++;
    // 	}
    // 	for(int i = 1;i <= n;i++){
    // 		sum += mp[a[i] + c];
    // 	}
    // 	cout << sum << endl;
    // 	return 0;
    // }

    3 烦恼的高考志愿

    题⽬来源: 洛⾕

    题⽬链接: P1678 烦恼的⾼考志愿

    难度系数: ★★

    【解法】

    分析题意:给点一个数b,然后在数组中找出离b最近的那个数

    解法一:利用set来解决

    解法二:排序+二分(找出大于等于B的最小的元素的位置)

    【参考代码】

    #include<iostream>
    #include<algorithm>
    using namespace std;typedef long long LL;
    const int N = 1e5 + 10;
    LL a[N];
    int m,n;
    LL ret;
    int main()
    {cin >> m >> n;for(int i = 1;i <= m;i++) cin >> a[i];sort(a,a+m+1);a[0] = -1e7 + 10;for(int i = 1;i <= n;i++){LL x;cin >> x;int left = 1,right = m;while(left < right){int mid = (left + right) / 2;if(a[mid] >= x) right = mid;else left = mid + 1;}ret += min(abs(a[left]-x),abs(a[left-1]-x));}cout << ret << endl;return 0;
    }

    二、 ⼆分答案

    准确来说,应该叫做「⼆分答案 + 判断」。

    ⼆分答案可以处理⼤部分「最⼤值最⼩」以及「最⼩值最⼤」的问题。如果「解空间」在从⼩到⼤的「变化」过程中,「判断」答案的结果出现「⼆段性」,此时我们就可以「⼆分」这个「解空间」,通过「判断」,找出最优解。

    刚接触的时候,可能觉得这个「算法原理」很抽象。没关系, 道题的练习过后,你会发现这个「⼆分答案」的原理其实很容易理解,重点是如何去「判断」答案的可⾏性

    1 木材加⼯

    题⽬来源: 洛⾕

    题⽬链接: P2440 ⽊材加⼯

    难度系数: ★★

    【解法】

    解法一:暴力解法(这个解法的时间复杂度O(n*L)->1e13,会超时)

    • 枚举所有的切割长度x
    • 求出在x的情况下,能切出来多少段->C
    • 找出C>=k的情况下,最大的x

    解法二:利用二分来优化

    x表示:切割出来的小段长度

    c表示:在x的基础下,最多能切出来多少段

    k表示:最终要切出来的段数

    根据题意,可以发现如下性质,:

    • 当 x 增⼤的时候, c 在减⼩。也就是最终要切成的⻓度越⼤,能切的段数越少;
    •  当 x 减⼩的时候, c 在增⼤。也就是最终要切成的⻓度越⼩,能切的段数越多。

    那么在整个「解空间」里面,设最终的结果是 ret ,于是有:

    • 当x ≤ ret 时,c ≥ k 。也就是「要切的⻓度」⼩于等于「最优⻓度」的时候,最终切出来的段数「⼤于等于」k;
    • 当 x > ret时,c < k 。也就是「要切的⻓度」⼤于「最优⻓度」的时候,最终切出来的段数「⼩于」k ;

    在解空间中,根据 的位置,可以将解集分成两部分,具有「⼆段性」,那么我们就可以「⼆分答案」。

    当我们每次⼆分⼀个切成的⻓度 x 的时候,如何算出能切的段数 c ?

    • 很简单,遍历整个数组,针对每⼀根⽊头,能切成的段数就是 a[i] / x 。

    【参考代码】

    #include<iostream>
    using namespace std;typedef long long LL;
    const int N = 1e5 + 10;
    LL a[N];
    int n,k;//当切割长度为mid的时候,最多能切出来多少段 
    LL calc(int mid)
    {LL c = 0;for(int i = 1;i <= n;i++){c += a[i] / mid;}return c;
    }
    int main()
    {cin >> n >> k;LL m = 0;for(int i = 1;i <= n;i++){cin >> a[i];m = max(m,a[i]);}LL left = 0,right = m;while(left < right){LL mid = (left + right + 1) / 2;if(calc(mid) >= k) left = mid;else right = mid - 1;}cout << left << endl;return 0;
    }

    2 砍树

    题⽬来源: 洛⾕

    题⽬链接:P1873 [COCI 2011/2012 #5] EKO / 砍树

    难度系数: ★★

    【解法】

    H表示:伐木机的高度

    C表示:当伐木机的高度为h的时候,所能获得的木材

    • 当 H 增⼤的时候, C 在减⼩;
    • 当 H 减⼩的时候, C 在增⼤。

    那么在整个「解空间」⾥⾯,设最终的结果是 ret ,于是有:

    当H<=ret 时 ,C>=M 。也就是「伐⽊机的⾼度」⼤于等于「最优⾼度」时,能得到的⽊材「⼩于等于」M ;

    当H>ret 时,C < M 。也就是「伐⽊机的⾼度」⼩于「最优⾼度」时,能得到的⽊材「⼤于」M 。

    在解空间中,根据 的位置,可以将解集分成两部分,具有「⼆段性」,那么我们就可以「⼆分答案」。
    当我们每次⼆分⼀个伐⽊机的⾼度 H 的时候,如何算出得到的⽊材 C ?

    • 很简单,遍历整个数组,针对每⼀根⽊头,能切成的⽊材就是 a[i] - H

    【参考代码】

    #include<iostream>
    using namespace std;
    typedef long long LL;
    const int N = 1e6 + 10;
    LL a[N];
    int n,m;// 当伐木机的高度为 x 时,所能获得的木材
    LL calc(int x)
    {LL c = 0;for(int i = 1;i <= n;i++){if(a[i] > x) c += a[i] - x;}return c;
    }
    int main()
    {cin >> n >> m;LL maxh = 0;for(int i = 1;i <= n;i++){cin >> a[i];maxh = max(maxh,a[i]);}LL left = 1,right = maxh;while(left < right){LL mid = (left + right + 1) / 2;if(calc(mid) >= m) left = mid;else right = mid - 1;}cout << left << endl;return 0;
    }

    3 跳石头

    题⽬来源: 洛⾕

    题⽬链接: P2678 [NOIP2015 提⾼组] 跳⽯头

    难度系数: ★★

    【解法】

    x表示:最短的跳跃距离

    c表示:在跳跃距离为x的情况下,移走的岩石

    根据题意,我们可以发现如下性质:

    • 当 x 增⼤的时候, c 也在增⼤;
    • 当 x 减⼩的时候, c 也在减⼩。

    那么在整个「解空间」⾥⾯,设最终的结果是 ret ,于是有:

    • 当 时x ≤ ret,c ≤ M。也就是「每次跳的最短距离」⼩于等于「最优距离」时,移⾛的⽯头块数「⼩于等于」M ;
    • 当 时x > ret,c > M。也就是「每次跳的最短距离」⼤于「最优距离」时,移⾛的⽯头块数「⼤于」 M。

    在解空间中,根据ret 的位置,可以将解集分成两部分,具有「⼆段性」,那么我们就可以「⼆分答案」。

    当我们每次⼆分⼀个最短距离 x 时,如何算出移⾛的⽯头块数 c ?

    • 定义前后两个指针 i, j 遍历整个数组,设 i ≤ j ,每次 j 从 i 的位置开始向后移动;
    • 当第⼀次发现 a[j] - a[i] ≥ x 时,说明 [i + 1, j - 1] 之间的⽯头都可以移⾛;
    • 然后将 i 更新到 j 的位置,继续重复上⾯两步。

    【参考代码】

    #include<iostream>
    using namespace std;const int N = 5e4 + 10;
    int a[N];
    int l,n,m;
    //当最短跳跃距离为x时,移走的岩石数目 
    int calc(int x)
    {int ret = 0;for(int i = 0;i <= n;i++){int j = i + 1;while(j <= n && a[j] - a[i] < x) j++;ret += j - i -1;i = j - 1;}return ret;
    }
    int main()
    {cin >> l >> n >> m;for(int i = 1;i <= n;i++) cin >> a[i];a[n+1] = l;n++;int left = 1,right = l;while(left < right){int mid = (left + right + 1) / 2;if(calc(mid) <= m) left = mid;else right = mid - 1;}cout << left << endl;return 0;} 
    

    http://www.dtcms.com/wzjs/335161.html

    相关文章:

  • 百度云空间能做网站吗推广代理平台
  • 免费搭建微信网站多少钱广州seo快速排名
  • 中日韩精品电影推荐网站2023年火爆的新闻
  • 基于php mysql的网站开发谷歌广告代理
  • 网站制作首选 新鸿儒建网站软件
  • 制作网页的软件免费沈阳seo
  • 做防水怎么注册网站营销软文300字范文
  • 自己做的网站怎么做客服聊天创意设计
  • 电子商务网站关键技术江苏seo技术教程
  • 在线代理服务器网站小说关键词生成器
  • 网站制作怎么样提供会员注册教育培训机构排名前十
  • 企业网站建设方案包含考证培训机构报名网站
  • 宁德市建设银行网站seo招聘
  • asp网站首页模板今日头条网页版
  • 制作图片视频的软件华为seo诊断及优化分析
  • 怎么在网站上做链接怎样在百度上做免费推广
  • 东海建设局网站手机网络优化
  • 做电影网站不放国内主机google广告
  • 本地wordpress后台进不去简述什么是seo
  • 做网站推广的公司好做吗宁波seo网络推广优化价格
  • 百度网站排名哪家好盘多多搜索引擎入口
  • 怎么做网站的效果图长沙做网站推广
  • b2c网站的认识简单的seo
  • 百度搜不到网站seo常见优化技术
  • 网站开发流程电话seo技术培训
  • 腾讯云做视频网站百度开放平台
  • 做直播网站需要学什么广告软文营销平台
  • 网站备案年检百度推广的方式有哪些
  • 网站域名怎么写好在线观看的seo综合查询
  • 东莞网站建设关键词seo关键词排名优化系统源码