Codeforces Round #627 (Div. 3) D. Pair of Topics
离散化+树状数组,O(n*log(2*n))的复杂度,实测运行841ms。
#include <bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int n,a[N],b[N],d[2*N],t[2*N],num1[2*N],num2[N];
struct node
{
int tr[2*N];
int lowbit(int x)
{return x&(-x);}
void add(int pos,int k)
{
for(int i=pos;i<=2*n;i+=lowbit(i))
tr[i]+=k;
}
int sum(int pos)
{
int s=0;
for(int i=pos;i;i-=lowbit(i))
s+=tr[i];
return s;
}
}T1,T2;//两个树状数组
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1;i<=n;i++)
{
cin>>b[i];
d[i]=a[i]-b[i];
d[i+n]=-d[i];//相反数
t[i]=d[i];//t是d的备份
t[i+n]=d[i+n];
}
stable_sort(t+1,t+2*n+1);
for(int i=1;i<=2*n;i++)
{
int k=lower_bound(t+1,t+2*n+1,d[i])-t;
num1[i]=k;//num是d离散化后的数组(总共)
T1.add(num1[i],1);
if(i>n)
{
num2[i-n]=k;
T2.add(num2[i-n],1);
}
}
long long ans=0;
for(int i=1;i<=n;i++)
{
T1.add(num1[i],-1);
T1.add(num2[i],-1);
T2.add(num2[i],-1);
int s1=T1.sum(2*n)-T1.sum(num2[i]);//总共比num2[i]大的数的个数
int s2=T2.sum(2*n)-T2.sum(num2[i]);//在相反数的数组中比num2[i]大的数的个数
ans+=s1-s2;
}
printf("%lld\n",ans);
return 0;
}
后来看了大佬们的代码,发现这题我又想复杂了,没必要上树状数组维护。
找到公式,类似尺取计数即可。O(n)的复杂度,实测运行156ms。
#include <bits/stdc++.h>
#define ll long long
using namespace std;
ll const maxn=2e5+5;
ll n,a[maxn],b[maxn],c[maxn],l,r,ans;
int main()
{
scanf("%lld",&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]=a[i]-b[i];
sort(c+1,c+1+n);
l=1,r=n,ans=0;
while(1)
{
if(c[l]+c[r]>0){ans+=r-l;r--;}
else l++;
if(r==l) break;
}
cout<<ans<<endl;
return 0;
}