World is Exploding
Problem Description
Given a sequence A with length n,count how many quadruple (a,b,c,d) satisfies:
a≠b≠c≠d,1≤a<b≤n,1≤c<d≤n,Aa<Ab,Ac>Ad
.
Input
The input consists of multiple test cases.
Each test case begin with an integer n in a single line.
The next line contains n integers A1,A2⋯An .
1≤n≤50000
0≤Ai≤1e9
Each test case begin with an integer n in a single line.
The next line contains n integers A1,A2⋯An .
1≤n≤50000
0≤Ai≤1e9
Output
For each test case,output a line contains an integer.
Sample Input
4 2 4 1 3 4 1 2 3 4
Sample Output
1 0
题意:
给出一个数列,要求你找出有多少个正序对和逆序对的四元组,下标均不相同且严格增减
分析:
首先计算出所有组合情况,观察发现对于每个端点其实只有四种情况不符合,即以当前点为端点的左升左降,左升右降,右升左降,右升右降右组合而成的四元组,那么对于每个端点用树状数组去统计左边和右边的可组成的正序对和逆序对个数即可,注意重复值特殊处理
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
#include<cstring>
using namespace std;
#define maxn 50005
vector<int>v;
int num[maxn],vis[maxn];
int pos[maxn],val[maxn];
int e1[maxn],e2[maxn];
int lg[maxn],rg[maxn],ls[maxn],rs[maxn];
int c[2][maxn];
int n;
bool cmp1(int a,int b)
{
if(val[a]==val[b]) return pos[a]<pos[b];
return val[a]<val[b];
}
bool cmp2(int a,int b)
{
if(val[a]==val[b]) return pos[a]<pos[b];
return val[a]>val[b];
}
int lowbit(int x)
{
return x&-x;
}
void update(int kind,int x,int val)
{
for(;x<=n;x+=lowbit(x)) c[kind][x]+=val;
}
int query(int kind,int x)
{
if(x==0) return 0;
int sum=0;
for(;x>0;x-=lowbit(x)) sum+=c[kind][x];
return sum;
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
memset(vis,0,sizeof vis);
v.clear();
for(int i=1;i<=n;i++)
{
pos[i]=i;
scanf("%d",&val[i]);
v.push_back(val[i]);
e1[i]=e2[i]=i;
}
sort(v.begin(),v.end());
v.erase(unique(v.begin(),v.end()),v.end());
for(int i=1;i<=n;i++)
{
val[i]=1+(lower_bound(v.begin(),v.end(),val[i])-v.begin());
}
for(int i=1;i<=n;i++)
{
num[i]=vis[val[i]];
vis[val[i]]++;
}
sort(e1+1,e1+n+1,cmp1);
sort(e2+1,e2+n+1,cmp2);
memset(c,0,sizeof c);
long long all1=0,all2=0;
for(int i=1;i<=n;i++)
{
int e=e1[i];
lg[e]=query(0,pos[e]-1)-num[pos[e]];
update(0,pos[e],1);
all1+=lg[e];
e=e2[i];
rg[e]=query(1,pos[e]-1)-num[pos[e]];
update(1,pos[e],1);
all2+=rg[e];
}
memset(c,0,sizeof c);
for(int i=1;i<=n;i++)
{
int e=e1[i];
ls[e]=query(0,n)-query(0,pos[e]);
update(0,pos[e],1);
e=e2[i];
rs[e]=query(1,n)-query(1,pos[e]);
update(1,pos[e],1);
}
long long ans=all1*all2;
for(int i=1;i<=n;i++)
{
ans-=(long long)rs[i]*rg[i]+(long long)lg[i]*ls[i]+(long long)lg[i]*rg[i]+(long long)ls[i]*rs[i];
}
printf("%lld\n",ans);
}
return 0;
}