题目: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 花匠的更多相关文章

  1. Codevs 3289 花匠 2013年NOIP全国联赛提高组

    3289 花匠 2013年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 花匠栋栋种了一排花,每株花都 ...

  2. 【CodeVS 3289】【NOIP 2013】花匠

    http://codevs.cn/problem/3289/ dp转移,树状数组维护前缀max和后缀max进行优化,$O(nlogn)$. #include<cstdio> #includ ...

  3. 花匠(codevs 3289)

    题目描述 Description 花匠栋栋种了一排花,每株花都有自己的高度.花儿越长越大,也越来越挤.栋栋决定把这排中的一部分花移走,将剩下的留在原地,使得剩下的花能有空间长大,同时,栋栋希望剩下的花 ...

  4. noip2013 Day2 T2 花匠 解题报告

    题目: 3289 花匠 2013年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目描述 Description 花匠栋栋种了一排花,每株花都有自己的高度.花儿越长越大, ...

  5. 2013 Noip提高组 Day2

    3288积木大赛 正文 题目描述 春春幼儿园举办了一年一度的“积木大赛”.今年比赛的内容是搭建一座宽度为n的大厦,大厦可以看成由n块宽度为1的积木组成,第i块积木的最终高度需要是hi. 在搭建开始之前 ...

  6. codevs 1082 线段树练习 3(区间维护)

    codevs 1082 线段树练习 3  时间限制: 3 s  空间限制: 128000 KB  题目等级 : 大师 Master 题目描述 Description 给你N个数,有两种操作: 1:给区 ...

  7. BZOJ 3289: Mato的文件管理[莫队算法 树状数组]

    3289: Mato的文件管理 Time Limit: 40 Sec  Memory Limit: 128 MBSubmit: 2399  Solved: 988[Submit][Status][Di ...

  8. codevs 1285 二叉查找树STL基本用法

    C++STL库的set就是一个二叉查找树,并且支持结构体. 在写结构体式的二叉查找树时,需要在结构体里面定义操作符 < ,因为需要比较. set经常会用到迭代器,这里说明一下迭代器:可以类似的把 ...

  9. codevs 1576 最长上升子序列的线段树优化

    题目:codevs 1576 最长严格上升子序列 链接:http://codevs.cn/problem/1576/ 优化的地方是 1到i-1 中最大的 f[j]值,并且A[j]<A[i] .根 ...

随机推荐

  1. wordpress多站点配置

    wordpress作为全球第一的个人博客搭建平台一直在国内外有着较高的人气,从3.0版本开始就已经支持多站点的搭建.该功能可以让子站点运行主站点的程序,不需要再每个站点分别存放网站程序.最近更新的4. ...

  2. 【WCF】自定义错误处理(IErrorHandler接口的用法)

    当被调用的服务操作发生异常时,可以直接把异常的原始内容传回给客户端.在WCF中,服务器传回客户端的异常,通常会使用 FaultException,该异常由这么几个东东组成: 1.Action:在服务调 ...

  3. 七牛云:ckeditor JS SDK 结合 C#实现多图片上传。

    成功了,搞了2天.分享一下经验. 首先是把官方的那个例子下载下来,然后照如下的方式修改. 其中tempValue是一个全局变量. function savetoqiniu() { var upload ...

  4. Oracle第一步

    Oracle 启动数据库 Startup [NOMOUNT|MOUNT|OPEN|FORCE] [restrict] [pfile=filename] 启动实例,加载数据库,启动数据库 oRACLE关 ...

  5. win10电脑优化

    Windows10必做的优化 --道心 关闭服务 右键点击"此电脑",选择"管理",进入"计算机管理"窗口. 在左侧的菜单选择"服 ...

  6. Spring MVC入门

    1.什么是SpringMvc Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面.Spring 框架提供了构建 Web 应用程序的全功能 M ...

  7. Object是什么

    Object是什么 .Net程序员们每天都在和Object在打交道如果你问一个.Net程序员什么是Object,他可能会信誓旦旦的告诉你"Object还不简单吗,就是所有类型的基类" ...

  8. 微软将向Linux用户提供SQL Server程序

    微软公司(Microsoft Corp., MSFT)将向Linux操作系统的用户提供旗下一项最赚钱的产品,这是该公司几年前无法想像的举措.这家软件巨头周一表示,将向免费的Linux Server提供 ...

  9. AutoMapper(五)

    返回总目录 Dynamic和ExpandoObject映射 AutoMapper不用任何配置就可以从dynamic(动态)对象映射或映射到dynamic对象. namespace FifthAutoM ...

  10. Vue.js——60分钟组件快速入门(下篇)

    概述 上一篇我们重点介绍了组件的创建.注册和使用,熟练这几个步骤将有助于深入组件的开发.另外,在子组件中定义props,可以让父组件的数据传递下来,这就好比子组件告诉父组件:"嘿,老哥,我开 ...