统计长度为5的上升序列个数,

容易想到O(n^2)的dp

f[k,i]:=Σf[k-1,j] (1<=j<i,a[i]>a[j])

ans:=Σf[5,i]

但是显然会超时,需要考虑优化

怎样快速找到所有比当前高度小的状态的和呢?

答案很显然:树状数组

考虑到这题每个数<=10^9,我们要将其离散化,再映射到树状数组上

注意这题的最终答案爆int64,所以要用到高精度

 var f,tr:array[..,..] of int64; //tr[i,j]表示树状数组,序列长度为i时,末尾离散化后高度为j;树状数组不会爆int64
    ans,d:array[..] of integer;
    a,b,c:array[..] of longint;
    len,k,n,i,j:longint; function lowbit(x:longint):longint;
  begin
    exit(x and (-x));
  end; procedure add(z:int64);       //高精度加法
  var i,la,w,x:longint;
  begin
    fillchar(d,sizeof(d),);
    la:=;
    while z<> do
    begin
      la:=la+;
      d[la]:=z mod ;
      z:=z div ;
    end;
    if la>len then len:=la;
    inc(len);
    w:=;
    for i:= to len do
    begin
      x:=w+d[i]+ans[i];
      ans[i]:=x mod ;
      w:=x div ;
    end;
    if ans[len]= then dec(len);
  end; function sum(p,q:longint):int64;
  begin
    sum:=;
    while p> do
    begin
      sum:=sum+tr[q,p];
      p:=p-lowbit(p);
    end;
  end; procedure work(p,q,z:int64);   //将当前状态加入树状数组
  begin
    while p<=n do
    begin
      tr[q,p]:=tr[q,p]+z;
      p:=p+lowbit(p);
    end;
  end; begin
  while not eof do
  begin
    readln(n);
    fillchar(c,sizeof(c),);
    fillchar(tr,sizeof(tr),);
    fillchar(f,sizeof(f),);
    for i:= to n do
    begin
      read(a[i]);
      b[i]:=i;
    end;
    readln;
    sort(,n);
    c[b[]]:=;
    k:=;
    for i:= to n do    //离散化,注意重复的标相同的号
      if a[i]=a[i-] then
        c[b[i]]:=c[b[i-]]
      else begin
        inc(k);
        c[b[i]]:=k;
      end;
    fillchar(ans,sizeof(ans),);
    len:=;
    for i:= to n do
    begin
      f[,i]:=;
      work(c[i],,);
      for j:= to do
      begin
        f[j,i]:=sum(c[i]-,j-);    //dp
        if f[j,i]> then work(c[i],j,f[j,i]);  
      end;
      if f[,i]> then add(f[,i]);
    end;
    for i:=len downto do
      write(ans[i]);
    writeln;
  end;
end.

总复杂度为O(nlogn)

质量很高的一道题

var f,tr:array[0..5,0..50010] of int64; //tr[i,j]表示树状数组,序列长度为i时,末尾离散化后高度为j;树状数组不会爆int64

ans,d:array[0..100] of integer;

a,b,c:array[0..50010] of longint;

len,k,n,i,j:longint;

function lowbit(x:longint):longint;

begin

exit(x and (-x));

end;

procedure add(z:int64);       //高精度加法

var i,la,w,x:longint;

begin

fillchar(d,sizeof(d),0);

la:=0;

while z<>0 do

begin

la:=la+1;

d[la]:=z mod 10;

z:=z div 10;

end;

if la>len then len:=la;

inc(len);

w:=0;

for i:=1 to len do

begin

x:=w+d[i]+ans[i];

ans[i]:=x mod 10;

w:=x div 10;

end;

if ans[len]=0 then dec(len);

end;

function sum(p,q:longint):int64;

begin

sum:=0;

while p>0 do

begin

sum:=sum+tr[q,p];

p:=p-lowbit(p);

end;

end;

procedure work(p,q,z:int64);   //将当前状态加入树状数组

begin

while p<=n do

begin

tr[q,p]:=tr[q,p]+z;

p:=p+lowbit(p);

end;

end;

begin

while not eof do

begin

readln(n);

fillchar(c,sizeof(c),0);

fillchar(tr,sizeof(tr),0);

fillchar(f,sizeof(f),0);

for i:=1 to n do

begin

read(a[i]);

b[i]:=i;

end;

readln;

sort(1,n);

c[b[1]]:=1;

k:=1;

for i:=2 to n do    //离散化,注意重复的标相同的号

if a[i]=a[i-1] then

c[b[i]]:=c[b[i-1]]

else begin

inc(k);

c[b[i]]:=k;

end;

fillchar(ans,sizeof(ans),0);

len:=1;

for i:=1 to n do

begin

f[1,i]:=1;

work(c[i],1,1);

for j:=2 to 5 do

begin

f[j,i]:=sum(c[i]-1,j-1);    //dp

if f[j,i]>0 then work(c[i],j,f[j,i]);

end;

if f[5,i]>0 then add(f[5,i]);

end;

for i:=len downto 1 do

write(ans[i]);

writeln;

end;

end.

poj3378的更多相关文章

  1. [poj3378] Crazy Thairs (DP + 树状数组维护 + 高精度)

    树状数组维护DP + 高精度 Description These days, Sempr is crazed on one problem named Crazy Thair. Given N (1 ...

  2. [POJ3378]Crazy Thairs

    Problem 给你一个数列,让你求由五个元素组成的顺序对的个数. Solution DP:用DP[i][j]表示把第j个作为五元组中第i个的方案数 则DP[i][j]=sum{DP[k][j-1]} ...

  3. poj分类 很好很有层次感。

    初期: 一.基本算法:      (1)枚举. (poj1753,poj2965)      (2)贪心(poj1328,poj2109,poj2586)      (3)递归和分治法.      ( ...

  4. 【转】POJ题目分类推荐 (很好很有层次感)

    OJ上的一些水题(可用来练手和增加自信) (poj3299,poj2159,poj2739,poj1083,poj2262,poj1503,poj3006,poj2255,poj3094)初期: 一. ...

  5. 【转】ACM训练计划

    [转] POJ推荐50题以及ACM训练方案 -- : 转载自 wade_wang 最终编辑 000lzl POJ 推荐50题 第一类 动态规划(至少6题, 和 必做) 和 (可贪心) (稍难) 第二类 ...

  6. POJ 题目分类(转载)

    Log 2016-3-21 网上找的POJ分类,来源已经不清楚了.百度能百度到一大把.贴一份在博客上,鞭策自己刷题,不能偷懒!! 初期: 一.基本算法: (1)枚举. (poj1753,poj2965 ...

  7. (转)POJ题目分类

    初期:一.基本算法:     (1)枚举. (poj1753,poj2965)     (2)贪心(poj1328,poj2109,poj2586)     (3)递归和分治法.     (4)递推. ...

  8. acm常见算法及例题

    转自:http://blog.csdn.net/hengjie2009/article/details/7540135 acm常见算法及例题  初期:一.基本算法:     (1)枚举. (poj17 ...

  9. poj分类

    初期: 一.基本算法:      (1)枚举. (poj1753,poj2965)      (2)贪心(poj1328,poj2109,poj2586)      (3)递归和分治法.      ( ...

随机推荐

  1. 1037. Magic Coupon (25)

    #include<iostream> #include<vector> #include<stdio.h> #include<algorithm> us ...

  2. ORA-27102: out of memory并伴随OSD-00031的处理

    刚才客户电话过来说有个数据库起不来了,开发商搞了好久搞不掂,得要让我们去帮忙看看.过去到现场,发现数据库无法打开,连nomount模式都不可以.报错的内容大致如下: ORA-27102: out of ...

  3. NGUI系列教程十(Scroll View实现触摸滚动相册效果)

    NGUI中提供了两种Scroll View 一种是通过手指或鼠标滑动视图时移动平面物体,另一种则是直接移动摄像机,他们各有各的好处.但是NGUI提供的Scroll View很难实现类似Android ...

  4. 微软职位内部推荐-Pricipal Dev Manager for Application Ecosystem & Service

    微软近期Open的职位: Location: China, BeijingDivision: Operations System Group Engineering Group OverviewOSG ...

  5. Linux学习笔记(5)-进程管理

    进程简介 进程是正在执行的一个程序或命令,每一个进程都有自己的地址空间,并占有一定的系统资源.感性的认识,进程就是一个正在运行的程序 进程管理的作用 判断服务器的运行状态 查看系统中有哪些进程 杀死进 ...

  6. Codeforces Round #260 (Div. 1) C. Civilization 树的中心+并查集

    题目链接: 题目 C. Civilization time limit per test1 second memory limit per test256 megabytes inputstandar ...

  7. java模拟OSUnMapTbl[]

    问题描述: 任务就绪表,记录当前就绪的任务,就绪表中把64个优先级的任务分成8组,优先级的1-3bit表示OSRdyTbl[]中组别OSRedyGrp,优先级的4-6bit表示每组中就绪任务的位置,当 ...

  8. 关于ax+by=c的解x,y的min(|x|+|y|)值问题

    首先我们移动一下项,并强行让a>b. 然后我们可以画出这样一个图像 我们发现,在线段l与x轴交点处的下方,x,y的绝度值是递增的,所以我们不考虑那个最小点在下端. 之后我们发现在点的上端,因为斜 ...

  9. [转载]C# 中Web.config文件的读取与写入

    asp.net2.0新添加了对web.config直接操作的功能.开发的时候有可能用到在web.config里设置配置文件,其实是可以通过程序来设置这些配置节的. asp.net2.0需要添加引用: ...

  10. jquery下拉列表选中项改变时获取新选项的属性值

    $("#textSel").change(funtion(){ var selVal=$(this).val(); var selText=$("#textSel opt ...