双指针&整数二分思路总结

近日小伙伴说得口诀

图难在建模、贪心难在证明、数据结构难在实现、搜索难在剪支、动态规划难在状态表示
二分双指针难在单调性(所以说见到数组,能排序就排序,因为排序是二分和双指针的接口)

正题

本文将介绍双指针&二分的思路。先由具体题目,在抽象出一般方法。下面先上题目。

Pair of Topics

题目链接:https://codeforces.com/contest/1324/problem/D
题意:

The next lecture in a high school requires two topics to be discussed. The i-th topic is interesting by ai units for the teacher and by bi units for the students.

The pair of topics i and j (i<j) is called good if ai+aj>bi+bj (i.e. it is more interesting for the teacher).

Your task is to find the number of good pairs of topics.

Input
The first line of the input contains one integer n (2≤n≤2⋅105) — the number of topics.

The second line of the input contains n integers a1,a2,…,an (1≤ai≤109), where ai is the interestingness of the i-th topic for the teacher.

The third line of the input contains n integers b1,b2,…,bn (1≤bi≤109), where bi is the interestingness of the i-th topic for the students.

Output
Print one integer — the number of good pairs of topic.
input
5
4 8 2 6 2
4 5 4 1 3

output
7

input
4
1 3 2 4
1 3 2 4
output
0

阅读理解:先给出两个数组:a,b。两数组长度相同,a中元素为教师对第index(数组下标)个tipic的感兴趣程度,b则是学生。现在要求出good topic的pair数。就是一对topic瞒住ai + aj > bi + bj ,i和j就是一对好topic。求有多少对这样的topic。

思路:
法1:暴力,不重不漏地枚举每一对tipic。显然这个方法会TLE,因为n=2*1e5,O(n^2)的时间复杂度。
法2:1)、变形判断公式 2)、构造新判断条件 3)、排序,利用双指针
法3:与法2前两步相同,第3步也是排序,只不过后面用的是整数二分。

coding

法2:公式咋变形? ai + aj > bi + bj --> (ai - bi) + (aj - bj ) > 0 --> 也就是 ci + cj > 0.
问题就变成c数组中,两个数加起来大于0,的个数。这时候,排序,利用单调,最快找到刚好满足条件的最后一个点。然后累加答案即可。
ci + cj > 0 用双指针分析,关键是看l,r指针的方向l,r。枚举l端点,即系l端点单调增加(index不断增加),ci =- -cj,左边变大,右边也要变大,因为有负号,所以只能变小。因此l,r是对向的
初始化l= 0 ,r = n-1。r指针不用回溯,因为...之前的l是肯定包含l+1的。快就快在这里。
代码如下:

#include <bits/stdc++.h> 

using namespace std;
const int N  = 200010;
typedef long long LL;
int a[N],n;
int main(){
	#ifndef  ONLINE_JUDGE
		freopen("topics.txt","r",stdin);
	#endif
	cin >> n;
	for(int i = 0 ; i < n; i++) cin >> a[i];
	
	for(int i = 0; i < n; i++){
		int t; cin >> t;
		a[i] = a[i] - t;
	}
	sort(a,a+n);
	int l  , r = n-1;
	LL ans = 0;
	//枚举l
	for(int i = 0 ; i < n; i++) {
		l = i;
		while(r >=0 && a[l] + a[r] > 0) r--;
		ans += n - max(r,l) - 1;
	}
	cout << ans <<endl;
} 
今天先更新到这 下篇博客在更新第3个方法,二分。
原文地址:https://www.cnblogs.com/custoyth/p/14107361.html