BZOJ 2090 [Poi2010]Monotonicity 2 DP+线段树
来源:互联网 发布:商业公司顶级域名是 编辑:程序博客网 时间:2024/05/16 14:22
题意:
给出N个正整数a[1..N],再给出K个关系符号(>、<或=)s[1..k]。
选出一个长度为L的子序列(不要求连续),要求这个子序列的第i项和第i+1项的的大小关系为s[(i-1)mod K+1]。
求出L的最大值。
解析:
一眼考虑DP,不过这个DP我的确刚开始认为这是没有什么正确性的,然后我就不会辣,但是大家都说这题就是DP..
并且好像自己一顿想要构造也没有构造出来不合法的数据?
那我就只能回到自己刚开始的DP思路了。
设F[i]表示到第i位拿出来的最长序列长度。
所以下一个符号显然是确定的。
然后等于号的话,我们直接开一个数组记录哪一个值上一次出现的可行位置即可。
小于号,丢到线段树里面,线段树对权值开,记录一段权值区间最大的已出现的f值,查询直接拿最大就好了。
大于号同理,再开一个线段树丢进去即可。
复杂度,查询
最坏
代码:
#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define N 500100#define M 1000100#define MM 1000000#define lson l,mid,rt<<1#define rson mid+1,r,rt<<1|1 using namespace std;int n,k;int a[N];int next[M];int app[M];int f[N],can[M];char s[N];char tmp[2];int ma[M<<2],pos[M<<2],ma2[M<<2],pos2[M<<2];void pushup(int rt){ ma[rt]=ma[rt<<1],pos[rt]=pos[rt<<1]; if(ma[rt<<1|1]>ma[rt]) ma[rt]=ma[rt<<1|1],pos[rt]=pos[rt<<1|1];}void update(int p,int v,int l,int r,int rt){ if(l==r) { ma[rt]=v; pos[rt]=l; return; } int mid=(l+r)>>1; if(p<=mid)update(p,v,lson); else update(p,v,rson); pushup(rt);}int query(int L,int R,int l,int r,int rt){ if(L<=l&&r<=R) { return rt; } int ret=0; int mid=(l+r)>>1; if(L<=mid) { int tmp=query(L,R,lson); if(ma[tmp]>=ma[ret])ret=tmp; } if(R>mid) { int tmp=query(L,R,rson); if(ma[tmp]>ma[ret])ret=tmp; } pushup(rt); return ret;}void pushup2(int rt){ ma2[rt]=ma2[rt<<1],pos2[rt]=pos2[rt<<1]; if(ma2[rt<<1|1]>ma2[rt]) ma2[rt]=ma2[rt<<1|1],pos2[rt]=pos2[rt<<1|1];}void update2(int p,int v,int l,int r,int rt){ if(l==r) { ma2[rt]=v; pos2[rt]=l; return; } int mid=(l+r)>>1; if(p<=mid)update2(p,v,lson); else update2(p,v,rson); pushup2(rt);}int query2(int L,int R,int l,int r,int rt){ if(L<=l&&r<=R) { return rt; } int ret=0; int mid=(l+r)>>1; if(L<=mid) { int tmp=query2(L,R,lson); if(ma2[tmp]>=ma2[ret])ret=tmp; } if(R>mid) { int tmp=query2(L,R,rson); if(ma2[tmp]>ma2[ret])ret=tmp; } pushup2(rt); return ret;}int main(){ scanf("%d%d",&n,&k); for(int i=1;i<=n;i++)scanf("%d",&a[i]),app[a[i]]=n+1; for(int i=n;i>=1;i--)next[a[i]]=app[a[i]],app[a[i]]=i; for(int i=1;i<=k;i++) { scanf("%s",tmp); s[i]=tmp[0]; } f[1]=1; if(s[1]=='<')update(a[1],1,1,MM,1); else if(s[1]=='>')update2(a[1],1,1,MM,1); else can[a[1]]=1; for(int i=2;i<=n;i++) { if(can[a[i]]) f[i]=f[can[a[i]]]+1; int tmp=0; if(a[i]>1) tmp=query(1,a[i]-1,1,MM,1); if(ma[tmp]+1>f[i]) f[i]=ma[tmp]+1; tmp=0; if(a[i]<1000000) tmp=query2(a[i]+1,MM,1,MM,1); if(ma2[tmp]+1>f[i]) f[i]=ma2[tmp]+1; if(s[(f[i]-1)%k+1]=='<')update(a[i],f[i],1,MM,1); else if(s[(f[i]-1)%k+1]=='>')update2(a[i],f[i],1,MM,1); else can[a[i]]=i; } int ans=0; for(int i=1;i<=n;i++)ans=max(ans,f[i]); printf("%d\n",ans);}
0 0
- BZOJ 2090 [Poi2010]Monotonicity 2 DP+线段树
- bzoj 2090: [Poi2010]Monotonicity 2 动态规划+线段树
- 线段树优化DP [Poi2010]Monotonicity 2
- [Poi2010]Monotonicity 2 线段树
- bzoj 2090 [Poi2010]Monotonicity 2 树状数组 dp 贪心
- BZOJ2089&2090: [Poi2010]Monotonicity 2
- Poi2010 Monotonicity 2
- [Poi2010]Monotonicity 2
- [Poi2010]Monotonicity 2
- BZOJ2090/2089 [Poi2010]Monotonicity 2/Monotonicity
- BZOJ2090 POI2010 Monotonicity
- bzoj 1949 [Ceoi2006]Walk dp 线段树
- [DP] BZOJ 4574 [Zjoi2016]线段树
- 【BZOJ 2084 [Poi2010]Antisymmetry 回文树
- [BZOJ 2084]POI2010 Antisymmetry
- [BZOJ 2085]POI2010 Hamsters
- [BZOJ 2096]Poi2010 Pilots
- BZOJ 2095: [Poi2010]Bridges
- Android UI开发第二十四篇——Action Bar
- 取消UITableViewCell的选中状态
- 如何将遥感图像读为Emgucv的Image<gray,float>形式
- Java中如何读写cookie
- linux 查找目录或文件
- BZOJ 2090 [Poi2010]Monotonicity 2 DP+线段树
- 设计模式-组合模式
- 【bzoj3732】 network 最小生成树+lca
- Unity3D中世界坐标转换到NGUI坐标
- Hbase过滤器(一)
- MY BLOG
- [转]CMMI Level-3 各个过程域SP的分析
- UCL & USL过程控制上下限与产品公差及极差
- UCL & USL过程控制上下限与产品公差及极差