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.


posted @ 2016-05-31 17:39  一个响亮的蒟蒻  阅读(138)  评论(0编辑  收藏  举报