时间限制:1S / 空间限制:256MB
【在线测试提交传送门】
【问题描述】
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. 给定一个长度为n的整数序列,统计有多少个四重元素(a,b,c,d)满足条件: a≠b≠c≠d, 1≤a<b≤n, 1≤c<d≤n, Aa<Ab, Ac>Ad.
【输入格式】
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. 输入包含多组测试数据,对于每组测试数据: 第一行,一个整数n1≤n≤50000,表示序列元素的个数; 接下来n行,每行n个正是,表示A1,A2⋯An。0≤Ai≤1e9
【输出格式】
For each test case,output a line contains an integer. 对于每个测试事情,输出一行一个整数。
【输入样例1】
4 2 4 1 3 4 1 2 3 4
【输出样例1】
1 0
【题目来源】
2016 Multi-University Training Contest 5
【解题思路】
考虑容斥,我们知道(a,b)的对数,(c,d)的对数,两个乘起来,再减去不合法的就好了。
不合法的,显然就是长度为3的哪些重复计算的,只要减去就好了。
维护l[i]表示前面有多少个比他小,l1[i]前面有多少个比他大,
r[i]后面有多少个比他小,r1[i]有多少个比他大,然后容斥计算。
【参考代码】
#include<bits/stdc++.h>
using namespace std;
const int maxn = 5e4+7;
int d[maxn],n,a[maxn],l[maxn],r[maxn],l1[maxn],r1[maxn];;
int lowbit(int x){
return x&(-x);
}
void update(int x,int v){
for(int i=x;i<maxn;i+=lowbit(i))
d[i]+=v;
}
int get(int x){
int ans = 0;
for(int i=x;i;i-=lowbit(i))
ans+=d[i];
return ans;
}
map<int,int>H;
vector<int> V;
int main(){
while(scanf("%d",&n)!=EOF){
memset(l1,0,sizeof(l1));
memset(r1,0,sizeof(r1));
memset(l,0,sizeof(l));
memset(r,0,sizeof(r));
memset(d,0,sizeof(d));
V.clear();H.clear();
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
V.push_back(a[i]);
}
sort(V.begin(),V.end());
V.erase(unique(V.begin(),V.end()),V.end());
for(int i=0;i<V.size();i++)
H[V[i]]=i+1;
for(int i=1;i<=n;i++)a[i]=H[a[i]];
long long ans1=0,ans2=0,ans3=0;
for(int i=1;i<=n;i++){
l[i]=get(a[i]-1);
l1[i]=get(maxn-1)-get(a[i]);
update(a[i],1);
}
memset(d,0,sizeof(d));
for(int i=n;i>=1;i--){
r[i]=get(a[i]-1);
r1[i]=get(maxn-1)-get(a[i]);
update(a[i],1);
}
for(int i=1;i<=n;i++){
ans3+=1ll*l[i]*r[i];
ans3+=1ll*l1[i]*r1[i];
ans3+=1ll*l[i]*l1[i];
ans3+=1ll*r[i]*r1[i];
ans1+=l[i],ans2+=r[i];
}
cout<<ans1*ans2-ans3<<endl;
}
}