Solution -「CF 1132G」Greedy Subsequences
Link.
定义 最长贪心严格上升子序列(LGIS) 为满足以下两点的最长序列:
- 是 的子序列。
- 中任意相邻两项对应 中 ,则 且不存在 ,s.t. 。
求给定序列 的所有长度为 的子区间 LGIS 长度之和。
。
很套路地建立树模型,对于 ,连向最小地使得 的 ,那么 个结点构成一片森林。再根据 LGIS 的定义,一个结点若存在于区间,则以其子树内任意一点开头的 LGIS 的长度都会 。故只需要在 DFN 上维护线段树即可动态更新每个区间的答案。
还有呢,联想到这道题,令 的 DFN 为 即可,树并不需要建出来 owo!
/* Clearink */
#include <cstdio>
inline int rint () {
int x = 0; char s = getchar ();
for ( ; s < '0' || '9' < s; s = getchar () );
for ( ; '0' <= s && s <= '9'; s = getchar () ) x = x * 10 + ( s ^ '0' );
return x;
}
template<typename Tp>
inline void wint ( Tp x ) {
if ( x < 0 ) putchar ( '-' ), x = -x;
if ( 9 < x ) wint ( x / 10 );
putchar ( x % 10 ^ '0' );
}
inline int imax ( const int a, const int b ) { return a < b ? b : a; }
const int MAXN = 1e6;
int n, m, a[MAXN + 5], dfn[MAXN + 5];
int top, stk[MAXN + 5], siz[MAXN + 5];
struct SegmentTree {
int mx[MAXN << 2], tag[MAXN << 2];
inline void pushdn ( const int rt ) {
int& t = tag[rt];
if ( !t ) return ;
mx[rt << 1] += t, tag[rt << 1] += t;
mx[rt << 1 | 1] += t, tag[rt << 1 | 1] += t;
t = 0;
}
inline void pushup ( const int rt ) {
mx[rt] = imax ( mx[rt << 1], mx[rt << 1 | 1] );
}
inline void add ( const int rt, const int l, const int r,
const int al, const int ar ) {
if ( al <= l && r <= ar ) return ++mx[rt], ++tag[rt], void ();
int mid = l + r >> 1; pushdn ( rt );
if ( al <= mid ) add ( rt << 1, l, mid, al, ar );
if ( mid < ar ) add ( rt << 1 | 1, mid + 1, r, al, ar );
pushup ( rt );
}
inline int qmax ( const int rt, const int l, const int r,
const int ql, const int qr ) {
if ( ql <= l && r <= qr ) return mx[rt];
int mid = l + r >> 1, ret = 0; pushdn ( rt );
if ( ql <= mid ) ret = imax ( ret, qmax ( rt << 1, l, mid, ql, qr ) );
if ( mid < qr ) ret = imax ( ret, qmax ( rt << 1 | 1, mid + 1, r, ql, qr ) );
return ret;
}
} sgt;
int main () {
n = rint (), m = rint ();
for ( int i = 1; i <= n; ++i ) a[i] = rint (), dfn[i] = n - i + 1;
for ( int i = 1; i <= n; ++i ) {
for ( siz[i] = 1; top && a[stk[top]] < a[i]; siz[i] += siz[stk[top--]] );
stk[++top] = i;
}
for ( int i = 1; i < m; ++i ) sgt.add ( 1, 1, n, dfn[i], dfn[i] + siz[i] - 1 );
for ( int i = m; i <= n; ++i ) {
sgt.add ( 1, 1, n, dfn[i], dfn[i] + siz[i] - 1 );
wint ( sgt.qmax ( 1, 1, n, dfn[i], dfn[i - m + 1] ) );
putchar ( i ^ n ? ' ' : '\n' );
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现