最长不下降子序列


题目大意:

给定一个长度为 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. 解决:Uncaught TypeError: $ is not a function

    本来好好的,突然就出现的错误,不过这并不是什么难解决的错误: 我的问题是:在js文件里我定义了一个var $;变量,只要把这个去掉就没问题了. 出现这种错误的解决方法: 1,先看看你的jq文件是否已经 ...

  2. 网安等保-Linux服务器之最新Ubuntu-22.04-LTS系统内核优化与安全加固配置脚本使用分享

    关注「WeiyiGeek」公众号 设为「特别关注」每天带你玩转网络安全运维.应用开发.物联网IOT学习! 希望各位看友[关注.点赞.评论.收藏.投币],助力每一个梦想. 本章目录 目录 0x00 前言 ...

  3. 《吐血整理》进阶系列教程-拿捏Fiddler抓包教程(16)-Fiddler如何充当第三者,再识AutoResponder标签-上篇

    1.简介 Fiddler充当第三者,主要是通过AutoResponder标签在客户端和服务端之间,Fiddler抓包,然后改包,最后发送.AutoResponder这个功能可以算的上是Fiddler最 ...

  4. 【短道速滑九】仿halcon中gauss_filter小半径高斯模糊优化的实现

    通常,我们谈的高斯模糊,都知道其是可以行列分离的算法,现在也有着各种优化算法实现,而且其速度基本是和参数大小无关的.但是,在我们实际的应用中,我们可能会发现,有至少50%以上的场景中,我们并不需要大半 ...

  5. C/C++ Capstone 引擎源码编译

    Capstone 是一个轻量级的多平台.多架构的反汇编框架.Capstone 旨在成为安全社区中二进制分析和反汇编的终极反汇编引擎.Capstone的编译非常简单只需要一步即可轻松得到对应的Lib库文 ...

  6. DFS算法-求集合的所有子集

    目录 1. 题目来源 2. 普通方法 1. 思路 2. 代码 3. 运行结果 3. DFS算法 1. 概念 2. 解题思路 3. 代码 4. 运行结果 4. 对比 1. 题目来源 牛客网,集合的所有子 ...

  7. Java中如何创建不可变(immutable)类

    什么是不可变类 1. 不可变类是指类的实例一经创建完成,这个实例的内容就不会改变. 2. Java中的String和八个基本类型的包装类(Integer, Short, Byte, Long, Dou ...

  8. flink-cdc同步mysql数据到hive

    本文首发于我的个人博客网站 等待下一个秋-Flink 什么是CDC? CDC是(Change Data Capture 变更数据获取)的简称.核心思想是,监测并捕获数据库的变动(包括数据 或 数据表的 ...

  9. 工具推荐-使用RedisInsight工具对Redis集群CURD操作及数据可视化和性能监控

    关注「WeiyiGeek」公众号 设为「特别关注」每天带你玩转网络安全运维.应用开发.物联网IOT学习! 希望各位看友[关注.点赞.评论.收藏.投币],助力每一个梦想. 本章目录 目录 0x00 快速 ...

  10. logstash知识点

    Logstash是位于Data和Elasticsearch之间的一个中间件.Logstash是一个功能强大的工具,可与各种部署集成. 它提供了大量插件. 它从数据源实时地把数据进行采集,可帮助您解析, ...