• 【数学】Pair of Topics—CF1324D


    Pair of Topics—CF1324D

    思路

    很明显,需要对 a i + a j > b i + b j a_i + a_j > b_i + b_j ai+aj>bi+bj 化简:
    a i − b i > b j − a j a_i - b_i > b_j - a_j aibi>bjaj
    a i − b i > − ( a j − b j ) a_i - b_i > -(a_j - b_j) aibi>(ajbj)
    c i = a i − b i c_i = a_i - b_i ci=aibi,则:
    c i > − c j c_i > -c_j ci>cj
    c i + c j > 0 c_i + c_j > 0 ci+cj>0
    所求变成:
    满足 i < j i < j i<j c i + c j > 0 c_i + c_j > 0 ci+cj>0 的数量。

    可以看出,如果没有 i < j i < j i<j 这个要求,那么我们可以对 c c c 排序,遍历 i i i,对于每一个 c i c_i ci 用二分求出满足 c i + c j > 0 c_i + c_j > 0 ci+cj>0 的数量,再求和即可。

    其实我们恰恰可以上边的方法求出答案 r e s res res,然后再执行 r e s   / =   2 res~/=~2 res /= 2 就是在约束条件 i < j i < j i<j 下的答案。
    因为我们用这个方法遍历每一个 c i c_i ci 的时候,都多计算了其中 i ′ > j ′ i' > j' i>j c i ′ + c j ′ > 0 c_i' + c_j' > 0 ci+cj>0 的数量,而这样的一对 c i ′ , c j ′ c_i', c_j' ci,cj i ( 遍历过程中的 i ) = j ′ ( 当前的 j ′ ) i(遍历过程中的i) = j'(当前的j') i(遍历过程中的i)=j(当前的j) 时都是同时满足两个条件的。所以我们多计算的数量等于应该计算的数量,最终 r e s res res 除以 2 2 2 就是本题正确的答案。

    例如, i = 3 , j = 2 , c i = 666 , c j = − 666 i = 3, j = 2, c_i = 666, c_j = -666 i=3,j=2,ci=666,cj=666,我们在用上百年那个方法的时候会将这种情况也计算在内。但如果将 i , j i, j i,j 对调,我们发现 i = 2 , j = 3 , c i = − 666 , c j = 666 i = 2, j = 3, c_i = -666, c_j = 666 i=2,j=3,ci=666,cj=666 是同时满足两个条件的。同理,每一个满足两个条件的 i , j i, j i,j 都会其将 i , j i, j i,j 对调后的 i , j i, j i,j 都会错误地被当做正确情况计算在内。

    C o d e Code Code

    #include 
    #define int long long
    #define sz(a) ((int)a.size())
    #define all(a) a.begin(), a.end()
    using namespace std;
    using PII = pair<int, int>;
    using i128 = __int128;
    const int N = 2e5 + 10;
    
    int n;
    int c[N];
    
    void solve(int Case) {
    	cin >> n;
    	for (int i = 1; i <= n; i ++) cin >> c[i];
    	for (int i = 1; i <= n; i ++) {
    		int b; cin >> b;
    		c[i] -= b;
    	}
    	sort(c + 1, c + n + 1);
    	
    	int res = 0;
    	for (int i = 1; i <= n; i ++) {
    		int l = 1, r = n;
    		while (l < r) {
    			int mid = (l + r) / 2;
    			if (c[i] + c[mid] > 0) {
    				r = mid;
    			} else {
    				l = mid + 1;
    			}
    		}
    		if (c[i] + c[l] > 0) {
    			res += (n - l + 1) - (l <= i);
    		}
    	}
    	cout << "       ";
    	cout << res / 2 << "\n";
    }
    
    signed main() {
    	cin.tie(0)->ios::sync_with_stdio(false);
    	int T = 1;
    //	cin >> T; cin.get();
    	int Case = 0;
    	while (++ Case <= T) solve(Case);
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
  • 相关阅读:
    MediaCodec源码分析 createByCodecName流程
    c语言数据结构,你可能还不知道的顺序表
    [Firefox/快捷键] 禁用Ctrl-W快捷键
    新160个CrackMe算法分析-002-abexcm5
    Docker 快速部署 SpringBoot2 项目
    Origin常用功能
    电极的制作方法详解
    C++Mysql8.0数据库跨平台编程实战(中)
    TRex学习之旅一
    C++面向对象设计和使用
  • 原文地址:https://blog.csdn.net/suoper2656/article/details/134327211