Monotonicity 2[POI2010]
题目描述
给出N个正整数a[1..N],再给出K个关系符号(>、<或=)s[1..k]。
选出一个长度为L的子序列(不要求连续),要求这个子序列的第i项和第i+1项的的大小关系为s[(i-1)mod K+1]。
求出L的最大值。
输入
第一行两个正整数,分别表示N和K (N, K <= 500,000)。
第二行给出N个正整数,第i个正整数表示a[i] (a[i] <= 10^6)。
第三行给出K个空格隔开关系符号(>、<或=),第i个表示s[i]。
输出
一个正整数,表示L的最大值。
样例输入
7 3
2 4 3 1 3 5 3
< > =
样例输出
6
提示
选出的子序列为2 4 3 3 5 3,相邻大小关系分别是< > = < >。
【题解】
喜闻乐见的数据结构优化dp。看完了题,在演草纸上写了一句“动规吧?”,然后就把这句话放一边了。觉得二分应该能行,就写了个二分。怎么check呢?写了个dfs。后来跟wzz说这个事,大佬非常不理解地说:还不如直接深搜呢,白白地加个log。瞬间觉得好有道理啊,果然上午不知道干了些什么。
下午听讲题,自己连O(n^2)的转移方程都没写出来,简直了。正解思路很清奇,f[i]表示到i这一位最长的子序列长度,有了长度符号就定下来了。不等号按符号维护线段树,等号直接拿数组标记一下。线段树的下标是a[i]的权值,内容是f[i]的权值,这样区间查询满足不等号的最大值就非常快了。得出f[i]之后推出下一位的符号,更新相应的线段树或数组即可。
线段树是个好东西。上次方伯伯的玉米田用到了树状数组优化dp,这一次算是第二道数据结构优化dp。虽然在理论上来讲树状数组比线段树好打多了,可我始终还是更喜欢线段树。连续两天的dp题都是想过它是dp,但还是没按dp来做。学完一段时间以后dp能力下降得多了,想当初正在讲的时候也是不怕想正解的。原来以为自己不擅长数学和数据结构,现在看来dp也不是很行,集训要做的事还太多了啊。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int sj=;
char fh[sj];
int n,k,a[sj],f[sj],dh[],temp,jg,jd;
void bj(int &x,int y)
{
x=x>y?x:y;
}
struct Tree
{
int l,r,jz;
}ds[*],xs[*];
void bt1(int x,int y,int z)
{
ds[x].l=y;
ds[x].r=z;
if(y==z) return;
int mid=(y+z)>>;
bt1(x<<,y,mid);
bt1((x<<)|,mid+,z);
}
void bt2(int x,int y,int z)
{
xs[x].l=y;
xs[x].r=z;
if(y==z) return;
int mid=(y+z)>>;
bt2(x<<,y,mid);
bt2((x<<)|,mid+,z);
}
int query1(int x,int y,int z)
{
if(ds[x].l==y&&ds[x].r==z) return ds[x].jz;
int mid=(ds[x].l+ds[x].r)>>;
if(mid<y) return query1((x<<)|,y,z);
if(z<=mid) return query1(x<<,y,z);
return max(query1(x<<,y,mid),query1((x<<)|,mid+,z));
}
int query2(int x,int y,int z)
{
if(xs[x].l==y&&xs[x].r==z) return xs[x].jz;
int mid=(xs[x].l+xs[x].r)>>;
if(mid<y) return query2((x<<)|,y,z);
if(z<=mid) return query2(x<<,y,z);
return max(query2(x<<,y,mid),query2((x<<)|,mid+,z));
}
void update1(int x,int y,int z)
{
if(ds[x].l==ds[x].r&&ds[x].r==z)
{
ds[x].jz=y;
return;
}
int mid=(ds[x].l+ds[x].r)>>;
if(mid<z) update1((x<<)|,y,z);
if(z<=mid) update1(x<<,y,z);
ds[x].jz=max(ds[x<<].jz,ds[(x<<)|].jz);
}
void update2(int x,int y,int z)
{
if(xs[x].l==xs[x].r&&xs[x].r==z)
{
xs[x].jz=y;
return;
}
int mid=(xs[x].l+xs[x].r)>>;
if(mid<z) update2((x<<)|,y,z);
if(z<=mid) update2(x<<,y,z);
xs[x].jz=max(xs[x<<].jz,xs[(x<<)|].jz);
}
int main()
{
scanf("%d%d",&n,&k);
for(int i=;i<=n;i++)
{
scanf("%d",&a[i]);
bj(jd,a[i]);
}
for(int i=;i<=k;i++) cin>>fh[i];
bt1(,,jd);
bt2(,,jd);
for(int i=;i<=n;i++)
{
if(dh[a[i]]+>f[i]) f[i]=dh[a[i]]+;
if(a[i]!=jd)
{
temp=query1(,a[i]+,jd);
if(temp+>f[i]) f[i]=temp+;
}
if(a[i]!=)
{
temp=query2(,,a[i]-);
if(temp+>f[i]) f[i]=temp+;
}
temp=f[i]%k;
if(!temp) temp=k;
if(fh[temp]=='=') dh[a[i]]=f[i];
if(fh[temp]=='>') update1(,f[i],a[i]);
if(fh[temp]=='<') update2(,f[i],a[i]);
bj(jg,f[i]);
}
printf("%d",jg);
return ;
}
Monotonicity 2[POI2010]的更多相关文章
- [补档][Poi2010]Monotonicity 2
[Poi2010]Monotonicity 2 题目 给出N个正整数a[1..N],再给出K个关系符号(>.<或=)s[1..k]. 选出一个长度为L的子序列(不要求连续),要求这个子序列 ...
- BZOJ2090: [Poi2010]Monotonicity 2【线段树优化DP】
BZOJ2090: [Poi2010]Monotonicity 2[线段树优化DP] Description 给出N个正整数a[1..N],再给出K个关系符号(>.<或=)s[1..k]. ...
- 【BZOJ2090/2089】[Poi2010]Monotonicity 2 动态规划+线段树
[BZOJ2090/2089][Poi2010]Monotonicity Description 给出N个正整数a[1..N],再给出K个关系符号(>.<或=)s[1..k].选出一个长度 ...
- [Poi2010]Monotonicity 2 线段树
这道题考试的时候先打了个dfs暴力.又打了个O(n²)的动规.然后竟然心血来潮拍了一下..明明知道过不去的...然后水了50分(20个测试点这么多啊啊啊啊). 因为它已经提前给你如果长度为i时下一位的 ...
- Poi2010 Monotonicity 2
树状数组优化dp 可以证明最优解一定是通过之前的最优转移过来的,所以每一个点只需要保存以该节点为结尾的最长长度即可 对于不同符号,等于号维护数组,大于小于维护树状数组 #include<cstd ...
- #14 [BZOJ2090/2089] [Poi2010]Monotonicity 2/Monotonicity
题解: 首先想到了标算..然后证明了一发是错的(事实证明很智障) 先说正确性比较显然的O(n^2)算法 令f[i][j]表示前i个物品,匹配到第j个括号,最大值是多少 g[i][j]表示前i个物品,匹 ...
- BZOJ2090 : [Poi2010]Monotonicity 2
设f[i]表示以i为结尾的最长的合法序列的长度,=号直接维护,<号和>号用两棵树状数组维护即可,时间复杂度$O(n\log n)$. #include<cstdio> #def ...
- bzoj2089&2090: [Poi2010]Monotonicity
双倍经验一眼题... f[i][1/2]表示以i结尾,当前符号应该是</>的最长上升子序列, 用BIT优化转移就好 =的话就不用说了吧= = #include<iostream> ...
- [BZOJ2090/2089] [Poi2010]Monotonicity 2/Monotonicity 树状数组优化dp
这个dp乍看不科学,仔细一看更不科学,所以作为一个执着BOY,我决定要造数据卡死波兰人民,但是我造着造着就......证出来了......... 这个就是把 < > =分开讨论每次找到f[ ...
随机推荐
- 【知识整理】这可能是最好的RxJava 2.x 入门教程(二)
这可能是最好的RxJava 2.x入门教程系列专栏 文章链接: 这可能是最好的RxJava 2.x 入门教程(一) GitHub 代码同步更新:https://github.com/nanchen22 ...
- mongo中的分页查询
/** * @param $uid * @param $app_id * @param $start_time * @param $end_time * @param $start_page * @p ...
- 【Android Developers Training】 37. 共享一个文件
注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...
- bootstrap table 插件多语言切换
在bootstrap中的bootstrap table 插件在多语言切换的审核,只需要如下操作 引入bootstrap-table-locale-all.js文件 $('#Grid').bootstr ...
- if和for的应用
语句 顺序 结束加分号 分支 让程序根据条件不同执行不同的代码 if语句 if(条件){代码} if(条件){代码}else{代码} else if(条件){代码} if嵌套 switch...cas ...
- xUtils使用详细介绍
xUtils3使用详解 一.xUtils简介: xUtils是基于Afinal开发的目前功能比较完善的一个Android开源框架,官网:https://github.com/wyouflf/xUtil ...
- js中各个类型的转换总结
字符串转换为数组: 1 正则表达式var string=“abcdedef”var obj=string.replace(/(.)(?=[^$])/g,"$1,").split ...
- h5可预览 图片ajax上传 ,后台有点弱不知道数据怎么取,但是可以肯定数据上传成功了
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- (转载)Java自带的GUI性能监控工具Jconsole以及JisualVM简介
原文链接:http://blog.csdn.net/chendc201/article/details/22905503 1 Jconsole 1.1 简介以及连接 JConsole是一个基于JMX的 ...
- 测试框架:使用SONAR分析代码质量
介绍 Sonar是一个用于代码质量管理的开源平台,用于管理Java源代码的质量.通过插件机制,Sonar 可以集成不同的测试工具,代码分析工具,以及持续集成工具,比如pmd-cpd.checkstyl ...