标签+线段树+离散化好题。
题意:给定一个长度为的序列,问满足的三元组的个数。
数据范围:
首先,我们知道求满足且的二元组的个数的线段树做法是什么。
类比 P1198 [JSOI2008]最大数 ,假设现在有一个数组。我们扫一遍整个序列,扫到时。此时数组存的是在数列中位置下标中大小为的数字的个数。那么此时便可以得到:对于,在中比小的数字的个数。
那么对于原问题,。这个过程利用线段树即可完成统计。
最后注意:由于的值域过大,所以需先离散化。
Code:
#include<cstdio>
#include<iostream>
#include<algorithm>
#define ri register int
using namespace std;
const int MAXN=30020;
int n,a[MAXN];
int l[MAXN<<2],r[MAXN<<2],add[MAXN<<2],tot[MAXN];
long long sum[MAXN<<2],ans;
struct node{
int num,pla;
}shu[MAXN];
bool cmp(node a,node b)
{
return a.num < b.num;
}
void build(int p,int lft,int rit)
{
l[p]=lft,r[p]=rit;
if(l[p]==r[p]) return;
int mid=(lft+rit)>>1;
build(p <<1,lft,mid);
build(p <<1|1,mid+1,rit);
}
void pushupadd(int p)
{
add[p]=add[p <<1]+add[p <<1|1];
}
void update1(int p,int where,int k)
{
if(l[p]==where&&r[p]==where)
{
add[p]+=k;
return;
}
if(where<=r[p <<1]) update1(p <<1,where,k);
if(l[p <<1|1]<=where) update1(p <<1|1,where,k);
pushupadd(p);
}
int query1(int p,int lft,int rit)
{
if(lft>rit) return 0;
if(lft<=l[p]&&r[p]<=rit) return add[p];
int anstot=0;
if(lft<=r[p <<1]) anstot=query1(p <<1,lft,rit);
if(l[p <<1|1]<=rit) anstot+=query1(p <<1|1,lft,rit);
return anstot;
}
void pushup(int p)
{
sum[p]=sum[p <<1]+sum[p <<1|1];
}
void update2(int p,int where,long long k)
{
if(l[p]==where&&r[p]==where)
{
sum[p]+=k;
return;
}
if(where<=r[p <<1]) update2(p <<1,where,k);
if(l[p <<1|1]<=where) update2(p <<1|1,where,k);
pushup(p);
}
long long query2(int p,int lft,int rit)
{
if(lft>rit) return 0;
if(lft<=l[p]&&r[p]<=rit) return sum[p];
long long anstot=0;
if(lft<=r[p <<1]) anstot=query2(p <<1,lft,rit);
if(l[p <<1|1]<=rit) anstot+=query2(p <<1|1,lft,rit);
return anstot;
}
int main()
{
scanf("%d",&n);
for(ri i=1;i<=n;i++)
{
scanf("%d",&shu[i].num);
shu[i].pla=i;
}
sort(shu+1,shu+n+1,cmp);
a[shu[1].pla]=1;
for(ri i=2;i<=n;i++)
{
if(shu[i-1].num==shu[i].num) a[shu[i].pla]=a[shu[i-1].pla];
if(shu[i-1].num<shu[i].num) a[shu[i].pla]=a[shu[i-1].pla]+1;
}
build(1,1,n);
for(ri i=2;i<=n;i++)
{
update1(1,a[i-1],1);
tot[i]=query1(1,1,a[i]-1);
}
for(ri i=2;i<=n;i++)
{
update2(1,a[i-1],(long long)tot[i-1]);
ans+=query2(1,1,a[i]-1);
}
cout<<ans;
return 0;
}