题目大意
给一个长度为n的序列ai,定义五元组(i,j,k,l,m)满足:
1<=i<j<k<l<m<=n;
ai<aj<ak<al<am;
问序列中有多少个满足条件的五元组。
数据范围:1 <= n <= 50000, 0 <= ai <= 109
分析
算法分析
ª 首先可以想到一个简单的dp方程
设f[i][j]表示从前i个数中选择j个数且第j个数为a[i]的种数,则
f[i][j] = f[i’][j - 1], 0 < i’ < i 且 a[i’] < a[i]
直接作的时间复杂度是O(5 * n ^ 2)
ª 转移的时候其实是转移sum(f[i’][j-1]), 0 < i’ < i, 且a[i’] < a[i],具有区间性。
ª 利用树状数组优化转移时间复杂度
最后一次
要用
高精度!!!
可能会有重复的数。
代码
type
arr=array[0..100] of int64;
var
n,m:longint;
b:array[0..109000,0..5] of int64;
a1,b1,c2:arr;
a,c,c1:array[0..100000] of int64;
i,j:longint;
k:int64;
s:char;
procedure qsort(l,r:longint);
var
i,j,key,temp:longint;
begin
if l>=r then exit;
i:=l;j:=r;
key:=a[l+random(r-l+1)];
repeat
while (a[i]<key) do inc(i);
while (a[j]>key) do dec(j);
if i<=j then
begin
temp:=a[i];a[i]:=a[j];a[j]:=temp;
temp:=c[i];c[i]:=c[j];c[j]:=temp;
inc(i);dec(j);
end;
until i>j;
qsort(l,j);
qsort(i,r);
end;
function ji(a,b:arr):arr;
var
i,j,k:longint;
jia:arr;
begin
fillchar(jia,sizeof(jia),0);
if a[0]>b[0] then jia[0]:=a[0]
else jia[0]:=b[0];
for i:=1 to jia[0] do
begin
jia[i]:=jia[i]+a[i]+b[i];
jia[i+1]:=jia[i] div 10;
jia[i]:=jia[i] mod 10;
end;
if jia[jia[0]+1]>0
then inc(jia[0]);
ji:=jia;
end;
procedure add(x:qword);
var
i,j,k:longint;
begin
i:=1;
fillchar(c2,sizeof(c2),0);
c2:=a1;
fillchar(a1,sizeof(a1),0);
fillchar(b1,sizeof(b1),0);
while x<>0 do
begin
b1[i]:=x mod 10;
x:=x div 10;
i:=i+1;
end;
b1[0]:=i-1;
if b1[0]=0 then b1[0]:=1;
a1:=ji(b1,c2);
end;
procedure bian1(p:int64;c:int64;j:longint);
begin
while p<=n do
begin
b[p,j]:=b[p,j]+c;
p:=p+(p and (p xor (p-1)));
end;
end;
function tong1(p:int64;j:longint):int64;
begin
tong1:=0;
while p>0 do
begin
tong1:=tong1+b[p,j];
p:=p-(p and (p xor (p-1)));
end;
end;
begin
while not eof do
begin
readln(n);
fillchar(a,sizeof(a),0);
fillchar(c,sizeof(c),0);
fillchar(c1,sizeof(c1),0);
fillchar(a1,sizeof(a1),0);
fillchar(b,sizeof(b),0);
for i:=1 to n do
begin
read(a[i]);
c[i]:=i;
end;
readln;
qsort(1,n);
j:=0;
c1[c[1]]:=1;
for i:=1 to n do
begin
if a[i]=a[i-1]
then
c1[c[i]]:=c1[c[i-1]]
else
begin
c1[c[i]]:=j+1;
j:=j+1;
end;
end;
for i:=1 to n do
begin
add(tong1(c1[i]-1,4));
for j:=5 downto 2 do
begin
k:=tong1(c1[i]-1,j-1);
bian1(c1[i],k,j);
end;
bian1(c1[i],1,1);
end;
for i:=a1[0] downto 1 do
write(a1[i]);
writeln;
end;
end.