zoukankan      html  css  js  c++  java
  • poj 3378 Crazy Thairs

    题意/Description

        These days, Sempr is crazed on one problem named Crazy Thair. Given N (1 ≤ N ≤ 50000) numbers, which  are no more than 109, Crazy Thair is a group of 5 numbers {i, j, k, l, m} satisfying:

        1. 1 ≤ i < j < k < l < m  N

        2. Ai < Aj < Ak < Al < Am

      For example, in the sequence {2, 1, 3, 4, 5, 7, 6},there are four Crazy Thair groups: {1, 3, 4, 5, 6}, {2, 3, 4, 5, 6}, {1, 3, 4, 5, 7} and {2, 3, 4, 5, 7}.

    Could you help Sempr to count how many Crazy Thairs in the sequence?

     

    读入/Input

      Input contains several test cases. Each test case begins with a line containing a number N, followed by a line containing N numbers.

     

    输出/Output

      Output the amount of Crazy Thairs in each sequence.

     

    题解/solution

      网上的解题报告有两个解法:

        1:Dp+线段树+离散化+高精度

        2:树状数组+Dp+离散化+高精度

      靠,好复杂,又没有P语言,C语言不会翻,I give up it。然后LZH经过了N天N夜,在 big head 的叽叽咕咕下,在 pig 的乱搞下,AC啦。于是我狠狠的敲了一波标。

      讲一下DP:

        F[I,j]表示用a[i]结尾的长度为j的序列数目。

        F[I,j]= sum(F[k,j-1]) (1<=k<I且a[i]>a[k])

      因为读入的数有10^9大,而数列长度只有50000,想到离散化。可离散后,位置发生改变,排个序,在二分来查找。

    要找它前方的所有比它小的树的t-1之和,想到了单点更新区间查询,线段树和数状数组都可以维护。由于长度为5,用5个树。完成这些,会发现结果会爆int64,于是加个高精度。看完后,你肯定惊恐
     
    代码/Code
    type
      arr=record
        x,y:longint;
      end;
    
    var
      dp:array [0..50001,1..5] of int64;
      m,len,n,k:longint;
      f:array [0..50001] of longint;
      tree:array [0..50001] of arr;
      sum:array [0..101] of longint;
    
    procedure qsort(l,r:longint);
    var
      i,j,key,key1:longint;
      temp:arr;
    begin
      if l>=r then exit;
      i:=l; j:=r;
      key:=tree[(l+r) shr 1].x;
      key1:=tree[(l+r) shr 1].y;
      repeat
        while (tree[i].x<key) or (tree[i].x=key) and (tree[i].y<key1) do inc(i);
        while (tree[j].x>key) or (tree[j].x=key) and (tree[j].y>key1) do dec(j);
        if i<=j then
          begin
            temp:=tree[i]; tree[i]:=tree[j]; tree[j]:=temp;
            inc(i);dec(j);
          end;
      until i>j;
      qsort(l,j);
      qsort(i,r);
    end;
    
    function bit(n:longint):longint;
    begin
        exit(n and -n);
    end;
    
    procedure jf(n:qword);
    var
      i:longint;
      a,b:array [0..100] of longint;
    begin
      fillchar(a,sizeof(a),0);
      fillchar(b,sizeof(b),0);
      i:=-1;
      while n>0 do
        begin
          inc(i);
          a[i]:=n mod 10;
          n:=n div 10;
        end;
      i:=-1;
      while i<100 do
        begin
          inc(i);
          b[i]:=a[i]+sum[i]+b[i];
          if b[i]>=10 then
            begin
              inc(b[i+1]);
              b[i]:=b[i] mod 10;
            end;
        end;
      for i:=0 to 99 do
        sum[i]:=b[i];
    end;
    
    function count(n,j:longint):int64;
    var
      ans:int64;
    begin
      ans:=0;
      while n>0 do
        begin
          ans:=ans+dp[n,j];
          n:=n-bit(n);
        end;
      exit(ans);
    end;
    
    procedure update(n,j:longint;k:int64);
    begin
      while n<=m do
        begin
          dp[n,j]:=dp[n,j]+k;
          n:=n+bit(n);
        end;
    end;
    
    procedure dpp(n:longint);
    var
      tem:int64;
      i,j:longint;
    begin
      fillchar(dp,sizeof(dp),0);
      fillchar(sum,sizeof(sum),0);
      len:=1;
      for i:=1 to n do
        begin
          tem:=count(f[i]-1,4);
          jf(tem);
          for j:=5 downto 2 do
            begin
              tem:=count(f[i]-1,j-1);
              update(f[i],j,tem);
            end;
          update(f[i],1,1);
        end;
      len:=100;
      while(sum[len]=0) and (len>0) do dec(len);
      for i:=len downto 0 do
        write(sum[i]);
      writeln;
    end;
    
    procedure main;
    var
      i:longint;
    begin
      while not eof do
        begin
          readln(n);
          m:=n;
          for i:=1 to n-1 do
            begin
              read(tree[i].x);
              tree[i].y:=i;
            end;
          readln(tree[n].x);
          tree[n].y:=n;
          qsort(1,n);
          f[tree[1].y]:=1; k:=0;
          for i:=1 to n do
            begin
              if tree[i].x=tree[i-1].x then f[tree[i].y]:=f[tree[i-1].y] else
                begin
                  f[tree[i].y]:=k+1;
                  inc(k);
                end;
            end;
          dpp(n);
        end;
    end;
    
    begin
      main;
    end.


  • 相关阅读:
    DataGridView 设置行不可见时,与货币管理器的位置关联的行不能设置为不可见
    DataGridView 冻结列后出现 无法添加该列,原因是它被冻结并被置于未冻结的列之后
    sql 2000 查询中增加序号列,自动增加列
    SQL 语法大全
    清除vs2003vs2008起始页最近打开项目
    ALTER TABLE 修改表时 因为有一个或多个对象访问此列
    UNIX上C++程序设计守则(信号和线程)(上)
    Thread Cancel 指南
    [C++再学习系列] 深入new/delete:New的3种形态
    设计模式学习(六):重构与模式,推荐书籍(完)
  • 原文地址:https://www.cnblogs.com/zyx-crying/p/9319691.html
Copyright © 2011-2022 走看看