• 【CF1324D】Pair of Topics


      题意:给定一个长度为 $n$ 的序列,求出满足 $1 le i<j le n$ 且 $a_i+a_j>b_i+b_j$ 的 $(i,j)$ 对数。


      我们把 $a_i+a_j>b_i+b_j$ 变形,变成 $(a_i-b_i)+(a_j-b_j)>0$。

      令 $c_i=a_i-b_i;(1 le i le n)$,那么要求就只有 $c_i+c_j>0$ 了。

      对于 $1$ 到 $n$ 中每一个 $i$,我们都找到满足 $c_j>-c_i$ 的 $j$ 的个数,并加起来统计,这可以用 排序 + STL 或 二分 解决。

      因为对于 $i eq j$ 时,$(i,j)$ 和 $(j,i)$ 肯定有一个不满足 $i<j$,所以统计出来的答案有 恰好一半 是不满足 $i<j$ 的,要除以 $2$。

      时间复杂度 $O(n; log; n)$。


      在统计的时候,我们发现统计到的 $j$ 没有满足 $j eq i$。

      如果当前的 $i$ 满足 $2c_i>0$,即 $c_i>0$ 时,自己肯定会被统计到。

      所以答案是统计的值减去满足 $c_i>0$ 的 $i$ 的个数,再除以 $2$。

      参考代码:

    #include <algorithm>
    #include <cstdio>
    #define INF 1e9
    #define eps 1e-6
    typedef long long ll;
    
    int n, a[200010], b[200010], k;
    ll ans;                                // 注意开 long long
    
    int main(){
    
        scanf("%d", &n);
        for(int i = 1; i <= n; i++)
            scanf("%d", &a[i]);
        for(int i = 1, x; i <= n; i++)
            scanf("%d", &x), a[i] -= x;    // 此处 a_i 就等同于上面的 c_i
        
        std::sort(a + 1, a + n + 1);
        for(int i = 1; i <= n; i++){
            k = std::upper_bound(a + 1, a + n + 1, -a[i]) - a;    
            // 上面求的是第一个大于 -a_i 的数字的位置
            if(a[i] > 0) ans--;            // 特判 a_i > 0 的情况
            ans += (ll)n - k + 1;
        }
        
        printf("%lld
    ", ans >> 1);        // 答案要除以 2
    
        return 0;
    }
  • 相关阅读:
    Add函数求两个数的和,不能使用+号或其它算术运算符
    小刘同学的第八十六篇博文
    小刘同学的第八十五篇博文
    小刘同学的第八十四篇博文
    小刘同学的第八十三篇博文
    小刘同学的第八十二篇博文
    小刘同学的第八十一篇博文
    小刘同学的第八十篇博文
    小刘同学的第七十九篇博文
    小刘同学的第七十八篇博文
  • 原文地址:https://www.cnblogs.com/zengpeichen/p/12484976.html
Copyright © 2020-2023  润新知