题目描述
Erwin最近对一种叫"thair"的东西巨感兴趣。。。
在含有n个整数的序列a1,a2......an中,
三个数被称作"thair"当且仅当i<j<k且ai<aj<ak
求一个序列中"thair"的个数。
输入输出格式
输入格式:开始一个正整数n,
以后n个数a1~an。
输出格式:"thair"的个数
输入输出样例
说明
对样例2的说明:
7个"thair"分别是
1 2 31 2 41 2 31 2 41 3 42 3 42 3 4约定30%的数据n<=100
60%的数据n<=2000
100%的数据n<=30000
大数据随机生成
0<=a[i]<=maxlongint
练习树状数组的好题
#include<bits/stdc++.h>
#define N 30010
using namespace std;
namespace program{
int n,a[N],A[N],l[N],r[N],c1[N],c2[N],m;
//我们可以用树状数组c[val]记录已经被考虑的数中小于val的个数,初始化为0,每次更新时,调用add(A[i],1)。
inline int lowbit(int x){
return x&(-x);
}
inline void add(int *c,int k,int val){
while(k<=N){
c[k]+=val;
k+=lowbit(k);
}return;
}
inline int Sum(int *c,int k){
int res=0;
while(k>0){
res+=c[k];
k-=lowbit(k);
}return res;
}
inline int Find(int x){
return lower_bound(A+1,A+m+1,x)-A;
}
inline void work(){
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i],A[i]=a[i];
sort(A+1,A+n+1);
m=unique(A+1,A+n+1)-(A+1);//离散化
for(int i=1;i<=n;i++){
int oo=Find(a[i]);
add(c1,oo,1);//插入当前数字
l[i]=Sum(c1,oo-1);//比第i个数小且在其左边的数的个数为l[i]
}
for(int i=n;i>=1;i--){
int oo=Find(a[i]);
add(c2,oo,1);
r[i]=n-i-(Sum(c2,oo)-1);
}
long long res=0;
for(int i=2;i<n;i++)//枚举中间那个数
res+=(l[i]*r[i]);//乘法原理
cout<<res<<'\n';
return;
}
}
int main(){
program::work();
return 0;
}