题目描述

给出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]的更多相关文章

  1. [补档][Poi2010]Monotonicity 2

    [Poi2010]Monotonicity 2 题目 给出N个正整数a[1..N],再给出K个关系符号(>.<或=)s[1..k]. 选出一个长度为L的子序列(不要求连续),要求这个子序列 ...

  2. BZOJ2090: [Poi2010]Monotonicity 2【线段树优化DP】

    BZOJ2090: [Poi2010]Monotonicity 2[线段树优化DP] Description 给出N个正整数a[1..N],再给出K个关系符号(>.<或=)s[1..k]. ...

  3. 【BZOJ2090/2089】[Poi2010]Monotonicity 2 动态规划+线段树

    [BZOJ2090/2089][Poi2010]Monotonicity Description 给出N个正整数a[1..N],再给出K个关系符号(>.<或=)s[1..k].选出一个长度 ...

  4. [Poi2010]Monotonicity 2 线段树

    这道题考试的时候先打了个dfs暴力.又打了个O(n²)的动规.然后竟然心血来潮拍了一下..明明知道过不去的...然后水了50分(20个测试点这么多啊啊啊啊). 因为它已经提前给你如果长度为i时下一位的 ...

  5. Poi2010 Monotonicity 2

    树状数组优化dp 可以证明最优解一定是通过之前的最优转移过来的,所以每一个点只需要保存以该节点为结尾的最长长度即可 对于不同符号,等于号维护数组,大于小于维护树状数组 #include<cstd ...

  6. #14 [BZOJ2090/2089] [Poi2010]Monotonicity 2/Monotonicity

    题解: 首先想到了标算..然后证明了一发是错的(事实证明很智障) 先说正确性比较显然的O(n^2)算法 令f[i][j]表示前i个物品,匹配到第j个括号,最大值是多少 g[i][j]表示前i个物品,匹 ...

  7. BZOJ2090 : [Poi2010]Monotonicity 2

    设f[i]表示以i为结尾的最长的合法序列的长度,=号直接维护,<号和>号用两棵树状数组维护即可,时间复杂度$O(n\log n)$. #include<cstdio> #def ...

  8. bzoj2089&2090: [Poi2010]Monotonicity

    双倍经验一眼题... f[i][1/2]表示以i结尾,当前符号应该是</>的最长上升子序列, 用BIT优化转移就好 =的话就不用说了吧= = #include<iostream> ...

  9. [BZOJ2090/2089] [Poi2010]Monotonicity 2/Monotonicity 树状数组优化dp

    这个dp乍看不科学,仔细一看更不科学,所以作为一个执着BOY,我决定要造数据卡死波兰人民,但是我造着造着就......证出来了......... 这个就是把 < > =分开讨论每次找到f[ ...

随机推荐

  1. websocket多线程问题

    title: websocket多线程问题 date: 2017-06-28 11:21:24 categories: websocket tags: [websocket] --- 开发框架 spr ...

  2. 【Android Developers Training】 36. 设置文件共享

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  3. java变量的分类与初始化

    2017/6/25 首先学习java最权威的就是官方的文档了,今天从头读了文档,把一些小细节理清楚. 变量 Java语言里的变量分以下4类: 1. Instance Variables: (Non-S ...

  4. kbengine所有的demo源代码

    回复才可见的内容https://github.com/kbengine/kbengine_ue4_demo回复才可见的内容https://github.com/kbengine/kbengine_og ...

  5. Linux进程/内核模型

    内核必须实现一组服务和相应的接口,应用程序则可以使用这些接口,而不是直接与硬件打交道. Linux内核主要由以下5个子系统组成:进程调度.内存管理.虚拟文件系统.进程间通信以及设备驱动. 在这个组成中 ...

  6. 关于Net开发中一些SQLServer性能优化的建议

    一. ExecuteNonQuery和ExecuteScalar 对数据的更新不需要返回结果集,建议使用ExecuteNonQuery.由于不返回结果集可省掉网络数据传输.它仅仅返回受影响的行数.如果 ...

  7. QC使用:

    qc使用入门 qc使用安装篇:附链接http://www.cnblogs.com/alterhu/archive/2011/11/05/2237483.html qc使用配置篇:附链接http://w ...

  8. Spring实现IoC的多种方式

    目录 一.使用XML配置的方式实现IOC 二.使用Spring注解配置IOC 三.自动装配 四.零配置实现IOC 五.示例下载 控制反转IoC(Inversion of Control),是一种设计思 ...

  9. 跳跳棋(9018_1563)(BZOJ_2144)

    题目: Hzwer的跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子. 某一天,黄金大神和cjy用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在a,b,c这三个位置.他们要 ...

  10. 在Apworks数据服务中使用基于Entity Framework Core的仓储(Repository)实现

    <在ASP.NET Core中使用Apworks快速开发数据服务>一文中,我介绍了如何使用Apworks框架的数据服务来快速构建用于查询和管理数据模型的RESTful API,通过该文的介 ...