雙指標&整數二分思路總結
阿新 • • 發佈:2020-12-09
近日小夥伴說得口訣
圖難在建模、貪心難在證明、資料結構難在實現、搜尋難在剪支、動態規劃難在狀態表示
二分雙指標難在單調性(所以說見到陣列,能排序就排序,因為排序是二分和雙指標的介面)
正題
本文將介紹雙指標&二分的思路。先由具體題目,在抽象出一般方法。下面先上題目。
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個方法,二分。