题解:这一题说实话真心吊......
首先看到题目中的表达式,要求满足那个表达式的 i 和 j ,可以看出题目所要求的是一对逆序对,但是是在两个不同的序列中求逆序对(大概可以表达成 A[I]>B[J] I<J)。看到数据到一百万,冒泡求肯定不划算,所以想到用线段树。记得先离散化一下,然后在线段树上处理。处理方法如下:
记NUML[I]为从1到 I A[I]出现的个数,NUMR[I]同理(从I 到N),处理的时候和处理单个序列中逆序对 的方法很像,但是要注意下顺序而且 I<>J ,从左到右是先把NUML[I-1]更新,再统计个数。I从1到N。
话说我才知道用scanf 比cin 快- =
#include<iostream>
#include<cstring>
#include<cstdio>
#include<map>
using namespace std;
struct mine
{
int l,r,node;
};
mine tree[4000002];
map<int,int> m1;
void build(int k,int l,int r)
{
int mid;
tree[k].l=l; tree[k].r=r; tree[k].node=0;
if (l==r) return;
mid=(l+r)/2;
build(k*2,l,mid);
build(k*2+1,mid+1,r);
}
void _insert(int k,int l,int r,int p)
{
if (tree[k].r==r && tree[k].l==l)
{
tree[k].node+=p;
return;
}
int mid=(tree[k].l+tree[k].r)/2;
if (r<=mid) _insert(k*2,l,r,p);
else if (l>=mid+1) _insert(k*2+1,l,r,p);
else
{
_insert(k*2,l,mid,p);
_insert(k*2+1,mid+1,r,p);
}
tree[k].node=tree[k*2].node+tree[k*2+1].node;
}
int _count(int k,int l,int r)
{
if (tree[k].l==l && tree[k].r==r) return tree[k].node;
int mid=(tree[k].l+tree[k].r)/2;
if (r<=mid) return _count(k*2,l,r);
else if (l>=mid+1) return _count(k*2+1,l,r);
else
return _count(k*2,l,mid)+_count(k*2+1,mid+1,r);
}
int numl[1000002],numr[1000002],sum[1000002];
int main()
{
memset(tree,0,sizeof(tree));
int n,a[1000002]; long long ans=0;
scanf("%d",&n);
for (int i=1;i<=n;i++) scanf("%d",&a[i]);
int cnt=1;
for (int i=1;i<=n;i++)
{
if (!m1[a[i]]) m1[a[i]]=cnt++;
a[i]=m1[a[i]];
}
cnt=-1;
for (int i=1;i<=n;i++)
{
sum[a[i]]++;
numl[i]=sum[a[i]];
cnt=max(cnt,sum[a[i]]);
}
build(1,1,cnt);
for (int i=1;i<=n;i++)
numr[i]=sum[a[i]]-numl[i]+1;
for (int i=1;i<=n;i++)
{
_insert(1,numl[i-1],numl[i-1],1);
ans+=(i-_count(1,1,numr[i]));
}
cout <<ans;
return 0;
}