链接:https://ac.nowcoder.com/acm/contest/375/A


时间限制:C/C++ 1秒,其他语言2秒

空间限制:C/C++ 262144K,其他语言524288K

64bit IO Format: %lld

题目描述

给你一个1~n的排列A1,A2...AnA1,A2...An,问有多少个四元组(a,b,c,d),满足a < b < c < d且Aa<Ac<Ab<AdAa<Ac<Ab<Ad。

输入描述:

第一行一个数n。接下来一行n个数,描述排列A。

输出描述:

一行一个整数,表示满足要求的四元组个数。

示例1

输入

复制

4
1 3 2 4

输出

复制

1

备注:

n≤500n≤500

n^3暴力做法

#include<bits/stdc++.h>
using namespace std;
const int N=5e2+10;
int a[N],ans,n;
int main(){
cin>>n;
for(int i=1;i<=n;++i) scanf("%d",&a[i]);
for(int i=1;i<=n;++i){
for(int j=i+1;j<=n;++j){
int num=0;
for(int k=n;k>j;k--){
if(a[k]>a[j]) num++;
if(a[k]<a[j]&&a[k]>a[i]) ans+=num;
}
}
}
printf("%d\n",ans);
}

主席树做法:将数组a放到一颗主席树上,枚举 b,c下标,从树中查询1到b-1比a[c]小的个数t1,从树中查询c到n中bia[b]大的个数t2。answer=t1*t2;

#include<bits/stdc++.h>
using namespace std;
const int N=5e2+10;
int a[N],ans,n;
int rt[N*20],ls[N*20],rs[N*20],sum[N*20],mx,cnt;
void up(int pre,int &now,int l,int r,int pos){
now=++cnt;
sum[now]=sum[pre]+1;
ls[now]=ls[pre];
rs[now]=rs[pre];
if(l==r) return ;
int mid=l+r>>1;
if(pos<=mid) up(ls[pre],ls[now],l,mid,pos);
else up(rs[pre],rs[now],mid+1,r,pos);
}
int qu(int now,int l,int r,int ql,int qr){
if(ql>qr) return 0;
if(ql<=l&&r<=qr) return sum[now];
int ans=0;
int mid=l+r>>1;
if(ql<=mid) ans+=qu(ls[now],l,mid,ql,qr);
if(qr>mid) ans+=qu(rs[now],mid+1,r,ql,qr);
return ans;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;++i) {
scanf("%d",&a[i]);
mx=max(mx,a[i]);
}

for(int i=1;i<=n;++i){
up(rt[i-1],rt[i],1,mx,a[i]);
}


int ans=0;
for(int b=1;b<n;++b){
for(int c=b+1;c<=n;++c){
if(a[b]<=a[c]) continue;
int t1=qu(rt[b-1],1,mx,1,a[c]-1);
int t2=qu(rt[n],1,mx,a[b]+1,mx)-qu(rt[c],1,mx,a[b]+1,mx);
ans=ans+t1*t2;
}
}
printf("%d\n",ans);
}