最长不下降子序列


题目大意:

给定一个长度为 N 的整数序列:A\(_{1}\),A\(_{2}\),⋅⋅⋅,A\(_{N}\)。

现在你有一次机会,将其中连续的 K 个数修改成任意一个相同值。

请你计算如何修改可以使修改后的数列的最长不下降子序列最长,请输出这个最长的长度。

最长不下降子序列是指序列中的一个子序列,子序列中的每个数不小于在它之前的数。


题目思路:

我们考虑这样两个数组,f[ ],g[ ],分别表示以i为结尾的最长不下降子序列长度和以i为开始的最长子序列长度,那我们的答案如果在不考虑修改k个数这个条件时,我们的答案就是:f[i]+g[i]-1;

当我们再去考考虑修改k个连续数这个条件时,答案就变成了:max(\(\sum_{i = n}^{i-k>=1}\)f[i-k]+k+g[i],k);



这个答案可以被看为由三部分组成:f[i-k]以i-k为结尾 + 修改后的k个数 + g[i]以i为开始



所以在实现上我们考虑用权值线段树来优化寻找最长不下降子序列这个过程

权值线段树维护的是以离散化后的点为(结束/开始)的最长不下降子序列长度

先将原数据去重+离散化

然后先处理f[i] =query(1,1,tot,1,a[i])+1 ,每次查询query(1,1,tot,1,a[i]),查询在他之前的最长子序列,之后将f[i]插入a[i]的位置



例如:a[i]离散化以后为3,那我们此时的查询即为query(1,1,tot,1,3)

这样我们就是查询从1到3的最长不下降子序列,修改也是同理,将3的值改为max(val,f[i])



之后重建线段树,倒着处理g[i]

几乎是同样的方法,只不过在这个同时处理一下ans = max(ans,f[i-k]+k+g[i]);


代码实现:

# include<bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
#define ls u<<1
#define rs u<<1|1
int f[N],g[N];//f[]--以i为结尾的最长...,g[]--以i为开始的最长...
int a[N];
int n,k; struct seg{
int maxn[4*N];
void pushup(int u){
maxn[u] = max(maxn[ls],maxn[rs]);
}
void build(int u,int l,int r){
if(l == r){
maxn[u] = 0;
return;
}
int mid = l+r>>1;
build(ls,l,mid);
build(rs,mid+1,r);
pushup(u);
} void modify(int u,int l,int r,int pos,int val){
if(l == r){
maxn[u] = max(maxn[u],val);
return;
}
int mid = l+r>>1;
if(pos<=mid) modify(ls,l,mid,pos,val);
else modify(rs,mid+1,r,pos,val);
pushup(u);
}
int query(int u,int l,int r,int L,int R){
if(l==L&&r==R){
return maxn[u];
}
int mid = l+r>>1;
if(R<=mid) return query(ls,l,mid,L,R);
else if(L>mid) return query(rs,mid+1,r,L,R);
else return max(query(ls,l,mid,L,mid),query(rs,mid+1,r,mid+1,R));
}
}tr;
int b[N],tot;
int find(int u){
int l = 1,r = tot;
int ans;
while(l<r){
int mid = l+r>>1;
if(b[mid] >= u){
r = mid;
}
else l = mid+1;
}
return l;
} int main(){
cin>>n>>k;
for(int i = 1;i <= n;++i) {
cin>>a[i];
b[i] = a[i];
}
sort(b+1,b+1+n);
tot = 1;
for(int i = 2;i <= n;++i)//离散化+去重
{
if(b[i] != b[tot]){
b[++tot] = b[i];
}
} for(int i = 1;i <= n;++i)
{
a[i] = find(a[i]);
}
tr.build(1,1,tot);//处理f[i]
for(int i = 1;i <= n-k;++i){
f[i] = tr.query(1,1,tot,1,a[i])+1;
tr.modify(1,1,tot,a[i],f[i]);
} tr.build(1,1,tot);//处理完f[i]后重建线段树来啊处理g[i]
int ans = 0;
for(int i = n;i-k>=1;--i){
ans = max(ans,f[i-k]+k+tr.query(1,1,tot,a[i-k],tot));
g[i] = tr.query(1,1,tot,a[i],tot)+1;
tr.modify(1,1,tot,a[i],g[i]); }
cout<<ans<<endl; return 0;
}

最长不下降子序列(线段树优化dp)的更多相关文章

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

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

  2. [AGC011F] Train Service Planning [线段树优化dp+思维]

    思路 模意义 这题真tm有意思 我上下楼梯了半天做出来的qwq 首先,考虑到每K分钟有一辆车,那么可以把所有的操作都放到模$K$意义下进行 这时,我们只需要考虑两边的两辆车就好了. 定义一些称呼: 上 ...

  3. Codeforces Round #426 (Div. 2) D 线段树优化dp

    D. The Bakery time limit per test 2.5 seconds memory limit per test 256 megabytes input standard inp ...

  4. 【bzoj3939】[Usaco2015 Feb]Cow Hopscotch 动态开点线段树优化dp

    题目描述 Just like humans enjoy playing the game of Hopscotch, Farmer John's cows have invented a varian ...

  5. POJ 2376 Cleaning Shifts (线段树优化DP)

    题目大意:给你很多条线段,开头结尾是$[l,r]$,让你覆盖整个区间$[1,T]$,求最少的线段数 题目传送门 线段树优化$DP$裸题.. 先去掉所有能被其他线段包含的线段,这种线段一定不在最优解里 ...

  6. 洛谷$P2605\ [ZJOI2010]$基站选址 线段树优化$dp$

    正解:线段树优化$dp$ 解题报告: 传送门$QwQ$ 难受阿,,,本来想做考试题的,我还造了个精妙无比的题面,然后今天讲$dp$的时候被讲到了$kk$ 先考虑暴力$dp$?就设$f_{i,j}$表示 ...

  7. D - The Bakery CodeForces - 834D 线段树优化dp···

    D - The Bakery CodeForces - 834D 这个题目好难啊,我理解了好久,都没有怎么理解好, 这种线段树优化dp,感觉还是很难的. 直接说思路吧,说不清楚就看代码吧. 这个题目转 ...

  8. 4.11 省选模拟赛 序列 二分 线段树优化dp set优化dp 缩点

    容易想到二分. 看到第一个条件容易想到缩点. 第二个条件自然是分段 然后让总和最小 容易想到dp. 缩点为先:我是采用了取了一个前缀最小值数组 二分+并查集缩点 当然也是可以直接采用 其他的奇奇怪怪的 ...

  9. Codeforces 1603D - Artistic Partition(莫反+线段树优化 dp)

    Codeforces 题面传送门 & 洛谷题面传送门 学 whk 时比较无聊开了道题做做发现是道神题( 介绍一种不太一样的做法,不观察出决策单调性也可以做. 首先一个很 trivial 的 o ...

随机推荐

  1. 通过cpu热插拔解决rcu stall的问题

    在linux 3.10环境一次故障处理中,发现有类似如下打印: NFO: rcu_sched_state detected stalls on CPUs/tasks: {15 } (detected ...

  2. HMS Core Discovery第17期直播预告|音随我动,秒变音色造型师

    [导读] 随着音视频内容品类的不断丰富及音乐创作门槛不断降低,大量用户正热切的参与到全民创作的大潮中.我们应该怎么去拥抱移动端影音潜力市场?音频编辑又可以有什么新玩法? 本期直播<音随我动,秒变 ...

  3. CF165D Beard Graph(dfs序+树状数组)

    题面 题解 乍一看,单点修改,单链查询,用树链剖分维护每条链上白边的数量就完了, 还是--得写树链剖分吗?--3e5,乘两个log会T吗-- (双手颤抖) (纠结) 不!绝不写树链剖分! 这题如果能维 ...

  4. 未完待续【java】JavaEE学习路线总览

    这个博客会详细介绍各种技术的知识点,从零基础到入门,充当引路的作用. 同时也会发布一些Swift语言.c#语言.Xcode开发的学习笔记.一些阅读的笔记(部分读书笔记无法发布). 目前1-43的Jav ...

  5. 03_Linux基础-文件类型-主辅提示符-第1提示符-Linux命令-内外部命令-快捷键-改为英文编码-3个时间-stat-其他基础命令

    03_Linux基础-文件类型-主辅提示符-第1提示符-Linux命令-内外部命令-快捷键-改为英文编码-3个时间-stat-{1..100}-du-cd-cp-file-mv-echo-id-she ...

  6. PHP代码审计——文件操作漏洞

    梦想CMS(lmxcms)任意文件删除 1. 漏洞详情--CNVD-2020-59469   2. 漏洞描述称后台Ba***.cl***.php文件存在任意文件删除,查看cms源码,只有BackdbA ...

  7. QT学习(四)----360界面制作(1)

    参照网上的资料,模仿了一份360新特效的界面. 源代码在:http://download.csdn.net/detail/zhangyang1990828/5238013 360真实效果:(最好自己打 ...

  8. LibTorch 多项分布

    最近在学习过程中需要对服从某种分布的离散型随机变量进行抽样,在LibTroch中查到了torch::multinomial(多项分布),该方法的接口如下: at::Tensor multinomial ...

  9. Redis6.0.6的三大内存过期策略和八大淘汰策略

    一.前言 Redis在我们日常开发中是经常用到的,Redis也是功能非常强大,可以进行缓存,还会有一些排行榜.点赞.消息队列.购物车等等:当然还有分布式锁Redisson,我们使用肯定少不了集群!小编 ...

  10. 基于HBuilderX+UniApp+ThorUI的手机端前端开发处理

    现在的很多程序应用,基本上都是需要多端覆盖,因此基于一个Web API的后端接口,来构建多端应用,如微信.H5.APP.WInForm.BS的Web管理端等都是常见的应用.本篇随笔概括性的介绍基于HB ...