poj3378
统计长度为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的更多相关文章
- [poj3378] Crazy Thairs (DP + 树状数组维护 + 高精度)
树状数组维护DP + 高精度 Description These days, Sempr is crazed on one problem named Crazy Thair. Given N (1 ...
- [POJ3378]Crazy Thairs
Problem 给你一个数列,让你求由五个元素组成的顺序对的个数. Solution DP:用DP[i][j]表示把第j个作为五元组中第i个的方案数 则DP[i][j]=sum{DP[k][j-1]} ...
- poj分类 很好很有层次感。
初期: 一.基本算法: (1)枚举. (poj1753,poj2965) (2)贪心(poj1328,poj2109,poj2586) (3)递归和分治法. ( ...
- 【转】POJ题目分类推荐 (很好很有层次感)
OJ上的一些水题(可用来练手和增加自信) (poj3299,poj2159,poj2739,poj1083,poj2262,poj1503,poj3006,poj2255,poj3094)初期: 一. ...
- 【转】ACM训练计划
[转] POJ推荐50题以及ACM训练方案 -- : 转载自 wade_wang 最终编辑 000lzl POJ 推荐50题 第一类 动态规划(至少6题, 和 必做) 和 (可贪心) (稍难) 第二类 ...
- POJ 题目分类(转载)
Log 2016-3-21 网上找的POJ分类,来源已经不清楚了.百度能百度到一大把.贴一份在博客上,鞭策自己刷题,不能偷懒!! 初期: 一.基本算法: (1)枚举. (poj1753,poj2965 ...
- (转)POJ题目分类
初期:一.基本算法: (1)枚举. (poj1753,poj2965) (2)贪心(poj1328,poj2109,poj2586) (3)递归和分治法. (4)递推. ...
- acm常见算法及例题
转自:http://blog.csdn.net/hengjie2009/article/details/7540135 acm常见算法及例题 初期:一.基本算法: (1)枚举. (poj17 ...
- poj分类
初期: 一.基本算法: (1)枚举. (poj1753,poj2965) (2)贪心(poj1328,poj2109,poj2586) (3)递归和分治法. ( ...
随机推荐
- Node.js之【正则表达式函数之match、test、exec、search、split、replace使用详解】
1. Match函数 使用指定的正则表达式函数对字符串惊醒查找,并以数组形式返回符合要求的字符串 原型:stringObj.match(regExp) 参数: stringObj 必选项,需要去进行匹 ...
- 51nod1417 天堂里的游戏
---恢复内容开始--- 1417 天堂里的游戏 基准时间限制:1 秒 空间限制:131072 KB 分值: 10 难度:2级算法题 收藏 关注 多年后,每当Noder看到吉普赛人,就会想起那个遥 ...
- ThinkPHP图片上传
ThinkPHP是国内比较流行的轻量级的PHP框架,它在国内流行的一个最主要的因素在于它的说明文档非常健全完善,以及它源码内的注释都是中文的,方便于英语能力较差的程序员学习. 图片上传在网站里是很常用 ...
- JavaScript的常见事件和Ajax小结
一.常见事件类型 1.鼠标事件 事件名称 说明 onclick 鼠标单击时触发 ondbclick 鼠标双击时触发 onmousedown 鼠标左键按下时触发 onmouseup 鼠标释放时触发 on ...
- Huawei HG556a A版 刷 openwrt
一直想玩玩openwrt,调研了一下 HG556a尽管散热很烂,但性价比超高,于是淘宝入手一台A版,A版和C版区别为wifi芯片: 到货后在网上找了几个教程便开始动手刷openwrt,但刷机的过程中还 ...
- C语言创建一个窗口提示
打开Vs2012[我的是2012] /* X下面这些东西并没有什么用... 就不改了用2013 2015都一样 当然 devC++ 还有最原始的那个vc6.0也都是可以的. 编译环境遇到了相关问题网上 ...
- Perl中的特殊内置变量详解
#!/usr/bin/perl -w @array = qw(a b c d); foreach (@array) { print $_," "; } 例子的作用就是定义一个数组并 ...
- OO之策略模式
以下为策略模式详解: 引子: 使用策略就是要实现可扩展性,那么多态是不可少的.何谓可扩展性呢? 比如:我们用面向对象的思想来设计飞机,基类为飞机,飞机可以有很多种,客机,直升机,战斗机等,不同种类的飞 ...
- Netty多线程处理机制
技术点描述 本文主要研究NioServerSocketChannelFactory类和NioDatagramChannelFactory类, 以及这两个类的各自作用. 由于基于pipelineFact ...
- Mysql InnoDB彻底释放磁盘空间
Innodb数据库对于已经删除的数据只是标记为删除,并不真正释放所占用的磁盘空间,这就导致InnoDB数据库文件不断增长. 如果需要彻底释放磁盘空间,则需要先导出数据,然后删除数据文件,最后导入数据. ...