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] .根 ...
随机推荐
- Oracle分析函数入门
一.Oracle分析函数入门 分析函数是什么?分析函数是Oracle专门用于解决复杂报表统计需求的功能强大的函数,它可以在数据中进行分组然后计算基于组的某种统计值,并且每一组的每一行都可以返回一个统计 ...
- 学习AOP之深入一点Spring Aop
上一篇<学习AOP之认识一下SpringAOP>中大体的了解了代理.动态代理及SpringAop的知识.因为写的篇幅长了点所以还是再写一篇吧.接下来开始深入一点Spring aop的一些实 ...
- 多个Img标签之间的间隙处理方法
1.多个标签写在一行 <img src="/i/eg_tulip.jpg" alt="郁金香" height="100px"/> ...
- $.type 怎么精确判断对象类型的 --(源码学习2)
目标: var a = [1,2,3]; console.log(typeof a); //->object console.log($.type(a)); //->ar ...
- Ubuntu 16.10 安装KolourPaint 4画图工具
KolourPaint 4画图工具简单实用,可以绘画.视频处理和图标编辑: • 绘画:绘制图表和“手绘” • 视频处理:编辑截图和照片;应用特效 • 图标编辑:绘画剪贴和标识透明化 1.在Ubuntu ...
- 使用NUnit为游戏项目编写高质量单元测试的思考
0x00 单元测试Pro & Con 最近尝试在我参与的游戏项目中引入TDD(测试驱动开发)的开发模式,因此单元测试便变得十分必要.这篇博客就来聊一聊这段时间的感悟和想法.由于游戏开发和传统软 ...
- javascript运动系列第一篇——匀速运动
× 目录 [1]简单运动 [2]定时器管理 [3]分享到效果[4]移入移出[5]运动函数[6]透明度[7]多值[8]多物体[9]回调[10]函数完善[11]最终函数 前面的话 除了拖拽以外,运动也是j ...
- RabbitMQ + PHP (二)AMQP拓展安装
上篇说到了 RabbitMQ 的安装. 这次要在讲案例之前,需要安装PHP的AMQP扩展.不然可能会报以下两个错误. 1.Fatal error: Class 'AMQPConnection' not ...
- HTML5笔记2——HTML5音/视频标签详解
音视频的发展史 早期:<embed>+<object>+文件 问题:不是所有浏览器都支持,而且embed不是标准. 现状:Realplay.window media.Quick ...
- 流程表单中js如何清空SheetUser控件数据?
昨天有人问我js怎么清空.我试了试,发现简单的赋给他空值,并没有用.只能给他赋一个真实存在的值才有用.于是跟踪了一下他的删除按钮. 效果如下 使用场景:可以根据字段的不同类别变更人员. js代码如下, ...