【codeforces #627 D 】Pair of Topics

题目链接 http://codeforces.com/contest/1324/problem/D
由于数据规模大 O(n²)算法过不了

并没有想到用树状数组 …

a[i]+a[j]>b[i]+b[j];的话,那么a[i]-b[i]+(a[j]-b[j])也要大于0
这样我们存一个数组c[i]存的是a[i]-b[i];
这样我们就要求出来c[i]和c[j]的对数,使得c[i]+c[j]>0;

这样会分成3种情况:
1. 0和正整数的成对–>就是sum_0*sum_z;
2. 正整数和正整数成对–>用一下数学里的求和公式 (1+n)*n/2;
3. 就是负数和正数的情况了,我们采用二分搜索就好,注意当二分搜索出来的答案==n的时候要特别判断(c[l]是否大于c[n]);//这里我也wa了好几次

这个题一定要细节

还要注意这个东西
res+=(ll)((ll)(sum_z-1)/2*(ll)(1+sum_z-1));
//注意这里不能这样
//res+=(ll)((sum_z-1)/2*(1+sum_z-1));//这样也会整数溢出,整的我心态爆炸

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<string.h>
using namespace std;

typedef long long ll;

const int N=2e5+5;

ll a[N];
ll b[N];
ll c[N];

int main()
{
    int n;
    cin>>n;
    for(int i=1;i<=n;i++){
        scanf("%lld",&a[i]);
    }
    for(int i=1;i<=n;i++){
        scanf("%lld",&b[i]);
    }

    for(int i=1;i<=n;i++){
        c[i]=(ll)(a[i]-b[i]);
    }
    sort(c+1,c+1+n);
    int sum_z=0;
    int sum_0=0;
    int sum_f=0;
    for(int i=1;i<=n;i++){
        if(c[i]>0){
            sum_z++;
        }
        if(c[i]==0){
            sum_0++;
        }
        if(c[i]<0){
            sum_f++;
        }
    }
    ll res=0;
    //if(sum_z>1)

    if((sum_z-1)%2==0){
        res+=(ll)((ll)(sum_z-1)/2*(ll)(1+sum_z-1));
        //注意这里不能这样
        //res+=(ll)((sum_z-1)/2*(1+sum_z-1));//这样也会整数溢出,整的我心态爆炸
    }
    else{
        res+=(ll)((ll)(1+sum_z-1)/2*(ll)(sum_z-1));
    }
    //if(sum_z>=0)
    res+=(ll)(sum_0*sum_z);
    //cout<<"res="<<res<<endl;
    for(int i=1;i<=sum_f;i++){
        int l=i+1,r=n;
        while(l<r){
            int mid=(l+r)/2;
            if(abs(c[i])<c[mid]){
                r=mid;
            }else{
                l=mid+1;
            }
        }
        if(c[l]>abs(c[i]))
            res+=(ll)(n-l+1);
    }
    cout<<res<<endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_44833767/article/details/104875112
今日推荐