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


    近日小伙伴说得口诀

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

    正题

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

    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个方法,二分。
    
  • 相关阅读:
    ZOJ 3769 Diablo III(分组背包)
    HDU 1712 ACboy needs your help(分组背包入门题)
    POJ 1170 Shopping Offers(完全背包+哈希)
    HDU 4489 The King’s Ups and Downs
    [转] LINUX 三种网络连接模式
    [转] 软件架构
    [转] 支付宝系统架构内部剖析
    [转] pip镜像升级报警 -trust-host问题解决方案
    [转] Linux 查找文件内容
    [转] CentOS系统目录学习
  • 原文地址:https://www.cnblogs.com/custoyth/p/14107361.html
Copyright © 2020-2023  润新知