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)递归和分治法. ( ...
随机推荐
- php微信支付(仅pc端扫码支付模式二)详细步骤.----仅适合第一次做微信开发的程序员
本人最近做了微信支付开发,是第一次接触.其中走了很多弯路,遇到的问题也很多.为了让和我一样的新人不再遇到类似的问题,我把我的开发步骤和问题写出来,以供参考. 开发时间是2016/8/10,所以微信支付 ...
- php获取数组中重复数据的两种方法
分享下php获取数组中重复数据的两种方法. 1,利用php提供的函数,array_unique和array_diff_assoc来实现 <?php function FetchRepeatMem ...
- sql新感悟(where 1 = 1)
花了好久把YII框架看完发现一本很不错的书:SQL案例解析(清华大学出版社),看到一些比较有用的东西,感觉应该把他记录下来,看了好多页发现书中一直有 where 1=1,这样的语句,查过发现“wher ...
- xml学习总结(三)
复杂Schema 扩展包含简单内容的复杂类型 <?xml version="1.0" encoding="UTF-8"?> <xs:schem ...
- 帝国cms中 内容分页的SEO优化
关于内容页如果存在分页的话,我们想区分第一页和后面数页,当前的通用做法是在标题上加入分页码,帝国cms中如何做到呢.我们可以修改在e/class/functions.php中的源码.找到找到GetHt ...
- K2 Blackpearl 4.6.8 安装步骤详解
由于某些原因,我幼小的心灵受到了很大的创伤,倍感世态之炎凉,久久不能愈合,也因此很久没再接触K2 Blackpearl了.偶然来了兴趣,想整个K2的环境,闲暇之余了解其新功能,温故知新,也希望从中能讨 ...
- UML include、generalization、extend、association
1.别人的说法 转自:http://www.cnblogs.com/shinings/archive/2009/04/21/1440765.html 共性:都是从现有的用例中抽取出公共的那部分信息,作 ...
- google calendar api v3
google api for .net nuget Install-Package Google.Apis.Calendar.v3 oauth2 for asp.net http://www.code ...
- iOS 跳转到系统的设置界面-b
在项目中,我们经常会碰到使用位置的需求.当用户设置app不允许使用位置的时候,最好的用户体验就是直接调转到系统的位置设置界面,进行设置. 本人已经测试,在5c iOS8.3系统 和 5s iOS7.1 ...
- man手册使用
1.是普通的命令 2.是系统调用,如open,write之类的(通过这个,至少可以很方便的查到调用这个函数,需要加什么头文件) 3.是库函数,如printf,fread 4.是特殊文件,也就是/dev ...