题目链接 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;
}