rt
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+5;
int n,ans;
int a[N],lcnt[N],lsum[N],rcnt[N],rsum[N];
class SegmentTree{
#define lp p<<1
#define rp p<<1|1
public:
struct node{
int l,r,sum,tag;
}tr[N*4];
void pushup(int p){
tr[p].sum=tr[lp].sum+tr[rp].sum;
}
void build(int p,int l,int r){
tr[p].l=l,tr[p].r=r;
if(l==r){
//tr[p].sum=a[l];
return;
}
int mid=l+r>>1;
build(lp,l,mid);
build(rp,mid+1,r);
//pushup(p);
}
void spread(int p){
if(tr[p].tag){
tr[lp].sum+=tr[p].tag*(tr[lp].r-tr[lp].l+1);
tr[rp].sum+=tr[p].tag*(tr[rp].r-tr[rp].l+1);
tr[lp].tag+=tr[p].tag;
tr[rp].tag+=tr[p].tag;
tr[p].tag=0;
}
}
void change(int p,int l,int r,int v){
if(l<=tr[p].l&&r>=tr[p].r){
tr[p].sum+=v*(tr[p].r-tr[p].l+1);
tr[p].tag+=v;
return;
}
spread(p);
int mid=tr[p].l+tr[p].r>>1;
if(l<=mid)
change(lp,l,r,v);
if(r>mid)
change(rp,l,r,v);
pushup(p);
}
int query(int p,int l,int r){
if(l<=tr[p].l&&r>=tr[p].r)
return tr[p].sum;
spread(p);
int mid=tr[p].l+tr[p].r>>1;
int ans=0;
if(l<=mid)
ans+=query(lp,l,r);
if(r>mid)
ans+=query(rp,l,r);
return ans;
}
};
SegmentTree seg;
void init(){
int tmp[n]={};
for(int i=1;i<=n;i++)
tmp[i]=a[i];
sort(tmp+1,tmp+1+n);
int len=unique(tmp+1,tmp+1+n)-(tmp+1);
for(int i=1;i<=n;i++)
a[i]=lower_bound(tmp+1,tmp+1+len,a[i])-tmp;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
init();
for(int i=1;i<=n;i++){
lcnt[a[i]]++;
lsum[i]=lcnt[a[i]];
}
for(int i=n;i>=1;i--){
rcnt[a[i]]++;
rsum[i]=rcnt[a[i]];
}
seg.build(1,1,n);
for(int i=n;i>=1;i--){
ans+=seg.query(1,1,lsum[i]-1);
seg.change(1,rsum[i],rsum[i],1);
}
cout<<ans;
return 0;
}