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[ ...
随机推荐
- 既然函数也是对象,那么为什么this不指向普通函数?
function a(){ var b=1; function exp(){ alert(this.b); } exp(); } var b=2; a(); 既然函数是对象,且exp是在a中运行的,那 ...
- 【Android Developers Training】 15. 启动一个Activity
注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...
- 统计学习方法 三 kNN
KNN (一)KNN概念: K近邻算法是一种回归和分类算法,这主要讨论其分类概念: K近邻模型三要素: 1,距离: 2,K值的选择: K值选择过小:模型过复杂,近似误差减小,估计误差上升,出现过拟合 ...
- AngularJS服务和路由
colnplie 网页加载的出现一次 link 元素每次改变的时候 **$watch** 监听列表 $scope.$watch("name",functio ...
- Android-->创建自定义控件
1.仿 iPhone 的风格,在界面的顶部放置一个标题栏. <?xml version="1.0" encoding="utf-8"?> <R ...
- [图形学] Chp10 OpenGL三维观察程序示例
10.10节书中给出了一个程序示例,有一个填充正方形,从侧面的角度观察并画到屏幕上. 图0 这里进一步画出一个立方体,将相机放入立方体中心,旋转相机,达到在立方体中旋转看到不同画面的效果. 步骤: 1 ...
- H5编辑器核心算法和思想-遁地龙卷风
代码和特性在chrome49下测试有效. 文本渲染的本质是对文本节点的渲染,通过浏览器内置的对象Range可以获得选择的起始点.与终止点 var range = getRangeObject(); ...
- Django学习(一)---基本配置及创建项目、应用
安装:在Django官网下载最新版Django然后通过pip安装即可 一.创建项目 进入文件夹,打开cmd窗口,输入django-admin startproject myblog(项目名) 二.创建 ...
- Django学习(二)---使用模板Templates
学会使用渲染模板的方法来显示html内容. 一.Templates是什么: HTML文件 使用了Django模板语言(Django Tamplate Language DTL) 可以使用第三方模板 二 ...
- jsp 按钮颜色
jsp 按钮颜色 第一种方法 <input style= "color:#FF0000;background-color:#00FF00;" type="butto ...