codevs 3289 花匠
题目:codevs 3289 花匠
链接:http://codevs.cn/problem/3289/
这道题有点像最长上升序列,但这里不是上升,是最长“波浪”子序列。用动态规划可以解决,方程类似最长上升子序列:
f[i]=max(f[j]) ( 1≤j≤i-1 && ( (f[j]%2=1 && A[j]<A[i] ) || (j%2=0 && A[j]>A[i]) ) )
p[i]=max(p[i]) ( 1≤j≤i-1 && ( (p[j]%2=1 && A[j]>A[i] ) || (j%2=0 && A[j]<A[i]) ) )
结果:
ans=max(f[n],p[n])
...写出来,很恶心的方程,因为题目中是有两种情况,第一种是 第一个元素 < 第二个元素 开始的波浪序列,另一种是 第一个元素 > 第二个元素 开始的波浪序列。我这里的f[i]是第一种情况算出来的最长波浪序列,p[i]是第二种情况算出来的最长波浪序列,然后最后的答案是两者之间选一个最大的。这样用o(n²)的算法可以达成,但是注意,题目中的数据量是10,000 ,肯定时间要超,所以还是要用优化。
最长上升子序列中可以用线段树优化,那么这里怎么优化呢?
我的笨笨做法是开4个线段树:maxfj[],maxfo[],maxpj[],maxpo[]。
maxfj[]维护f[i]是奇数的最大值,maxfo[]维护f[i]是偶数的最大值。
maxpj[]维护p[i]是奇数的最大值,maxpo[]维护p[i]是偶数的最大值。
因为f[i]中,当f[i]是奇数的时候,区间是1到A[i]-1中的最大值,而当f[i]是偶数的时候,区间是A[i]+1到n的最大值(因为是严格单调,所以要+1或-1)。
当p[i]是奇数的时候,区间是A[i]+1到n的最大值,而当p[i]是偶数的时候,区间是1到A[i]-1中的最大值。
所以不能同时维护,要分开来,因此就是4个线段树。
当然,A[i]的值很大,要做离散化。
大致思路就是这样吧。
附代码:
#include<cstdio>
#include<algorithm>
#include<iostream>
using namespace std;
const int maxn=; int n,maxfj[maxn*],maxfo[maxn*],f[maxn],p[maxn],maxpj[maxn*],maxpo[maxn*]; struct u
{
int v,r;
bool operator <(const u &rhs) const
{
return v<rhs.v;
}
}A[maxn]; bool cmp(u a,u b)
{
return a.r<b.r;
} int w,v;
void updatefj(int o,int L,int R)
{
if(L==R) maxfj[o]=max(maxfj[o],v);
else
{
int M=(L+R)/;
if(w<=M) updatefj(o*,L,M); else updatefj(o*+,M+,R);
maxfj[o]=max(maxfj[o*],maxfj[o*+]);
}
} int y1,y2,ans;
void queryfj(int o,int L,int R)
{
if(y1<=L && R<=y2) ans=max(ans,maxfj[o]);
else
{
int M=(L+R)/;
if(y1<=M) queryfj(o*,L,M);
if(y2>M) queryfj(o*+,M+,R);
}
}
void updatefo(int o,int L,int R)
{
if(L==R) maxfo[o]=max(maxfo[o],v);
else
{
int M=(L+R)/;
if(w<=M) updatefo(o*,L,M); else updatefo(o*+,M+,R);
maxfo[o]=max(maxfo[o*],maxfo[o*+]);
}
} void queryfo(int o,int L,int R)
{
if(y1<=L && R<=y2) ans=max(ans,maxfo[o]);
else
{
int M=(L+R)/;
if(y1<=M) queryfo(o*,L,M);
if(y2>M) queryfo(o*+,M+,R);
}
}
void updatepj(int o,int L,int R)
{
if(L==R) maxpj[o]=max(maxpj[o],v);
else
{
int M=(L+R)/;
if(w<=M) updatepj(o*,L,M); else updatepj(o*+,M+,R);
maxpj[o]=max(maxpj[o*],maxpj[o*+]);
}
} void querypj(int o,int L,int R)
{
if(y1<=L && R<=y2) ans=max(ans,maxpj[o]);
else
{
int M=(L+R)/;
if(y1<=M) querypj(o*,L,M);
if(y2>M) querypj(o*+,M+,R);
}
} void updatepo(int o,int L,int R)
{
if(L==R) maxpo[o]=max(maxpo[o],v);
else
{
int M=(L+R)/;
if(w<=M) updatepo(o*,L,M); else updatepo(o*+,M+,R);
maxpo[o]=max(maxpo[o*],maxpo[o*+]);
}
} void querypo(int o,int L,int R)
{
if(y1<=L && R<=y2) ans=max(ans,maxpo[o]);
else
{
int M=(L+R)/;
if(y1<=M) querypo(o*,L,M);
if(y2>M) querypo(o*+,M+,R);
}
} int main()
{
cin>>n;
for(int i=;i<=n;i++) cin>>A[i].v,A[i].r=i;
//离散化
sort(A+,A+n+);
for(int i=,nw=;i<=n;i++)
{
f[i]=,p[i]=;//顺便做的f[],p[]初始化
if(A[i+].v!=A[i].v) nw++,A[i].v=nw-;
else A[i].v=nw;
}
sort(A+,A+n+,cmp); w=A[].v,v=f[];
updatefj(,,n);
updatepj(,,n); for(int i=;i<=n;i++)
{
y1=,y2=A[i].v-,ans=;
if(y2>=y1) queryfj(,,n);//注意,因为有A[i]-1,所以要判断区间的存在
y1=A[i].v+,y2=n;
if(y2>=y1) queryfo(,,n);
f[i]=ans+;
v=f[i],w=A[i].v;
if(f[i]%==) updatefj(,,n);
else updatefo(,,n); y1=,y2=A[i].v-,ans=;
if(y2>=y1) querypo(,,n);
y1=A[i].v+,y2=n;
if(y2>=y1) querypj(,,n);
p[i]=ans+;
v=p[i],w=A[i].v;
if(p[i]%==) updatepj(,,n);
else updatepo(,,n);
} cout<<max(f[n],p[n]);
return ;
}
codevs 3289 花匠的更多相关文章
- Codevs 3289 花匠 2013年NOIP全国联赛提高组
3289 花匠 2013年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 花匠栋栋种了一排花,每株花都 ...
- 【CodeVS 3289】【NOIP 2013】花匠
http://codevs.cn/problem/3289/ dp转移,树状数组维护前缀max和后缀max进行优化,$O(nlogn)$. #include<cstdio> #includ ...
- 花匠(codevs 3289)
题目描述 Description 花匠栋栋种了一排花,每株花都有自己的高度.花儿越长越大,也越来越挤.栋栋决定把这排中的一部分花移走,将剩下的留在原地,使得剩下的花能有空间长大,同时,栋栋希望剩下的花 ...
- noip2013 Day2 T2 花匠 解题报告
题目: 3289 花匠 2013年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目描述 Description 花匠栋栋种了一排花,每株花都有自己的高度.花儿越长越大, ...
- 2013 Noip提高组 Day2
3288积木大赛 正文 题目描述 春春幼儿园举办了一年一度的“积木大赛”.今年比赛的内容是搭建一座宽度为n的大厦,大厦可以看成由n块宽度为1的积木组成,第i块积木的最终高度需要是hi. 在搭建开始之前 ...
- codevs 1082 线段树练习 3(区间维护)
codevs 1082 线段树练习 3 时间限制: 3 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description 给你N个数,有两种操作: 1:给区 ...
- BZOJ 3289: Mato的文件管理[莫队算法 树状数组]
3289: Mato的文件管理 Time Limit: 40 Sec Memory Limit: 128 MBSubmit: 2399 Solved: 988[Submit][Status][Di ...
- codevs 1285 二叉查找树STL基本用法
C++STL库的set就是一个二叉查找树,并且支持结构体. 在写结构体式的二叉查找树时,需要在结构体里面定义操作符 < ,因为需要比较. set经常会用到迭代器,这里说明一下迭代器:可以类似的把 ...
- codevs 1576 最长上升子序列的线段树优化
题目:codevs 1576 最长严格上升子序列 链接:http://codevs.cn/problem/1576/ 优化的地方是 1到i-1 中最大的 f[j]值,并且A[j]<A[i] .根 ...
随机推荐
- Castle Core 4.0.0 alpha001发布
时隔一年多以后Castle 项目又开始活跃,最近刚发布了Castle Core 4.0.0 的alpha版本, https://github.com/castleproject/Core/releas ...
- .NetCore中的日志(1)日志组件解析
.NetCore中的日志(1)日志组件解析 0x00 问题的产生 日志记录功能在开发中很常用,可以记录程序运行的细节,也可以记录用户的行为.在之前开发时我一般都是用自己写的小工具来记录日志,输出目标包 ...
- Java基础Map接口+Collections工具类
1.Map中我们主要讲两个接口 HashMap 与 LinkedHashMap (1)其中LinkedHashMap是有序的 怎么存怎么取出来 我们讲一下Map的增删改查功能: /* * Ma ...
- 一步一步教你用CSS画爱心
今天小颖给大家分享一个用CSS画的爱心,底下有代码和制作过程,希望对大家有所帮助. 第一步: 先画一个正方形.如图: <!DOCTYPE html> <html> <he ...
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(63)-Excel导入和导出-自定义表模导入
系列目录 前言 上一节使用了LinqToExcel和CloseXML对Excel表进行导入和导出的简单操作,大家可以跳转到上一节查看: ASP.NET MVC5+EF6+EasyUI 后台管理系统(6 ...
- java 线程 Lock 锁使用Condition实现线程的等待(await)与通知(signal)
一.Condition 类 在前面我们学习与synchronized锁配合的线程等待(Object.wait)与线程通知(Object.notify),那么对于JDK1.5 的 java.util.c ...
- python之最强王者(9)——函数
1.Python 函数 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段. 函数能提高应用的模块性,和代码的重复利用率.你已经知道Python提供了许多内建函数,比如print().但 ...
- 我的MYSQL学习心得(六) 函数
我的MYSQL学习心得(六) 函数 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据类 ...
- MemoryMappedFile 在 Mono in Linux 的开发笔记
前言 MemoryMappedFile(简称MMF)类是.NET中对内存映射文件进行操作的类,内存映射文件是非常高效的本地IO方案,由操作系统提供内存与IO文件之间的映射转换,对内存映射文件的更改由操 ...
- Javascript高级技巧
上次整理了Ajax部分,这周看完了高级技巧部分,也整理下吧. 1.类型检测 使用Object.prototype.toString.call(obj)的方式. 因为无论typeof还是instance ...