近日小伙伴说得口诀
图难在建模、贪心难在证明、数据结构难在实现、搜索难在剪支、动态规划难在状态表示
二分双指针难在单调性(所以说见到数组,能排序就排序,因为排序是二分和双指针的接口)
正题
本文将介绍双指针&二分的思路。先由具体题目,在抽象出一般方法。下面先上题目。
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个方法,二分。