poj 3378 Crazy Thairs
题目大意
给一个长度为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.