# poj 3378 Crazy Thairs

240人阅读 评论(3)

给一个长度为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;

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
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
c[i]:=i;
end;
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
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.


1
0

个人资料
• 访问：62521次
• 积分：3443
• 等级：
• 排名：第11509名
• 原创：249篇
• 转载：6篇
• 译文：2篇
• 评论：300条
qq邮箱