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] .根 ...
随机推荐
- AutoMapper:Unmapped members were found. Review the types and members below. Add a custom mapping expression, ignore, add a custom resolver, or modify the source/destination type
异常处理汇总-后端系列 http://www.cnblogs.com/dunitian/p/4523006.html 应用场景:ViewModel==>Mode映射的时候出错 AutoMappe ...
- Carousel 旋转画廊特效的疑难杂症
疑难杂症 该画廊特效的特点就是前后元素有层级关系. 我想很多人应该看过或者用过这个插件carousel.js,网上也有相关的教程.不知道这个插件的原型是哪个,有知道的朋友可以告诉我. 该插件相对完美, ...
- [C#] C# 知识回顾 - 你真的懂异常(Exception)吗?
你真的懂异常(Exception)吗? 目录 异常介绍 异常的特点 怎样使用异常 处理异常的 try-catch-finally 捕获异常的 Catch 块 释放资源的 Finally 块 一.异常介 ...
- Spring Enable annotation – writing a custom Enable annotation
原文地址:https://www.javacodegeeks.com/2015/04/spring-enable-annotation-writing-a-custom-enable-annotati ...
- 基于改进人工蜂群算法的K均值聚类算法(附MATLAB版源代码)
其实一直以来也没有准备在园子里发这样的文章,相对来说,算法改进放在园子里还是会稍稍显得格格不入.但是最近邮箱收到的几封邮件让我觉得有必要通过我的博客把过去做过的东西分享出去更给更多需要的人.从论文刊登 ...
- c#比较两个数组的差异
将DataTable中某一列数据直接转换成数组进行比较,使用的Linq,要引用命名空间using System.Linq; string[] arrRate = dtRate.AsEnumerable ...
- MongoDB集群配置
本文演示:(一个主服务器,一个备份服务器,三个仲裁服务器) 官方推荐副本集的成员数量为奇数,最多12个副本集节点,最多7个节点参与选举. 本文演示基于本机,用端口区分服务(每个服务器下新建db文件夹用 ...
- AndroidStudio — Error:Failed to resolve: junit:junit:4.12错误解决
原博客:http://blog.csdn.net/u013443865/article/details/50243193 最近使用AndroidStudio出现以下问题: 解决:打开app下的buil ...
- 对Maven、gradle、svn、spring 3.0 fragment、git的想法
1.Maven Maven可以构建项目,采用pom方式配置主项目和其他需要引用的项目.同时可结合spring3.0的新特性web fragment. 从现实出发,特别是对于管理不到位,程序员整体素质 ...
- 完美解决CodeSmith无法获取MySQL表及列Description说明注释的方案
问题描述: CodeSmith是现在比较实用的代码生成器,但是我们发现一个问题: 使用CodeSmith编写MySQL模板的时候,会发现一个问题:MySQL数据表中的列说明获取不到,也就是column ...