i,j,n,t:longint;
m:int64;
begin
readln(n);
for i:=1 to n do
read(a[i]);
m:=0;
for i:=1 to n do
begin
for j:=i+1 to n do
if a[i]>a[j] then m:=n-j+m;
end;
write(m);
end.
本题是一个动态规划题。
令数组a[i]表示当前元素。数组 b[i]表示i之前比a[i]大的数的个数,即把0 to i-1枚举一遍可得。而每个终止于a[i]的三元组对应前面两数比a[i]大的个数,故将所有0<j<j, 只要a[j]>a[i],则j可选,进而以j为中间数的三元组个数为b[j],故总个数为b[j]之和。时间复杂度0(n*n)。
此题还可用类似归并排序的方法优化到O(nlogn),但较为复杂,此题不需要。
我的程序就是用nlog n的归并排序写的
#include<iostream>
using namespace std;
int n,a[10001],add[10001];
int in[10001],out[10001];
void init()
{
int i;
cin>>n;
for (i=1;i<=n;i++)
{
cin>>a[i];
add[i]=i;
}
}
void type(int x,int y)
{
long long i,total=0;
for (i=x;i<=y;i++)
total=total+in[add[i]]*out[add[i]];
cout<<total;
}
void sort(int x1,int y1,int x2,int y2)
{
int p[10001],flag[10001],i,j,f1=x1,f2=x2;
for (i=x1;i<=y2;i++)
{
if ( f1<=y1 && f2<=y2 )
{
if ( a[f1]>a[f2] )
{
p[i]=a[f1];
flag[i]=add[f1];
out[add[f1]]=out[add[f1]]+(y2-f2+1);
for (j=f2;j<=y2;j++)
in[add[j]]=in[add[j]]+1;
f1++;
}
else
{
p[i]=a[f2];
flag[i]=add[f2];
f2++;
}
}
else
{
if ( f1<=y1 )
{
p[i]=a[f1];
flag[i]=add[f1];
f1++;
}
else
{
p[i]=a[f2];
flag[i]=add[f2];
f2++;
}
}
}
for (i=x1;i<=y2;i++)
{
a[i]=p[i];
add[i]=flag[i];
}
}
void pai(int x,int y)
{
int mid;
if ( x==y )
{
return;
}
else
{
mid=(x+y)/2;
pai(x,mid);
pai(mid+1,y);
sort(x,mid,mid+1,y);
}
}
main()
{
init();
pai(1,n);
type(1,n);
}