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] .根 ...
随机推荐
- Hawk 4.7 单步调试
单步调试的意义 已经编写的工作流,可能会因为某些外界环境的变化而出错,此时需要排除错误,我们可以使用单步调试. 单步调试的本质,相当于只使用前n个模块,这样就能看到每个步骤下,流的改变. 例子 还是上 ...
- RabbitMq应用一的补充(RabbitMQ的应用场景)
直接进入正题. 一.异步处理 场景:发送手机验证码,邮件 传统古老处理方式如下图 这个流程,全部在主线程完成,注册->入库->发送邮件->发送短信,由于都在主线程,所以要等待每一步完 ...
- Collection集合
一些关于集合内部算法可以查阅这篇文章<容器类总结>. (Abstract+) Collection 子类:List,Queue,Set 增: add(E):boolean addAll(C ...
- 【工具使用】mac电脑使用技巧
本文地址 分享提纲: 1. mac命令行和finder的交互 2. 一些mac的插件 3. 一些开发的配置 1.mac命令行和findder交互 1)命令行中打开当前文件夹: o ...
- DDD领域驱动设计 - 设计文档模板
设计文档模板: 系统背景和定位 业务需求描述 系统用例图 关键业务流程图 领域语言整理,主要是整理领域中的各种术语的定义,名词解释 领域划分(分析出子域.核心域.支撑域) 每个子域的领域模型设计(实体 ...
- “老坛泡新菜”:SOD MVVM框架,让WinForms焕发新春
火热的MVVM框架 最近几年最热门的技术之一就是前端技术了,各种前端框架,前端标准和前端设计风格层出不穷,而在众多前端框架中具有MVC,MVVM功能的框架成为耀眼新星,比如GitHub关注度很高的Vu ...
- 说说BPM数据表和日志表中几个状态字段的详细解释
有个客户说需要根据这些字段的值作为判断条件做一些定制化需求,所以需要知道这些字段的名词解释,以及里面存储的值具体代表什么意思 我只好为你们整理奉上这些了! Open Work Sheet 0 Sav ...
- H3 BPM产品安装手册(.Net版本)
1 安装说明 1.1 服务器安装必备软件 在使用该工作流软件之前,有以下一些软件是必须安装: l IIS7.0以上版本(必须): l .Net Framework 4.5(必 ...
- SpringMVC视图解析器
SpringMVC视图解析器 前言 在前一篇博客中讲了SpringMVC的Controller控制器,在这篇博客中将接着介绍一下SpringMVC视 图解析器.当我们对SpringMVC控制的资源发起 ...
- postgresql无法安装pldbgapi的问题
要对函数进行调试需要安装插件pldbgapi,当初在windows上面的postgresql实例中执行了一下语句就安装上了: create extension pldbgapi; 但是在linux中执 ...