Live2D

Solution -「CF 1132G」Greedy Subsequences

\(\mathcal{Description}\)

  Link.

  定义 \(\{a\}\) 最长贪心严格上升子序列(LGIS) \(\{b\}\) 为满足以下两点的最长序列:

  • \(\{b\}\)\(\{a\}\) 的子序列。
  • \(\{b\}\) 中任意相邻两项对应 \(\{a\}\)\(a_i,a_j\),则 \(a_i<a_j\) 且不存在 \(i<k<j\),s.t. \(a_i<a_k\)

  求给定序列 \(\{a_n\}\) 的所有长度为 \(k\) 的子区间 LGIS 长度之和。

  \(1\le k\le n\le10^6\)

\(\mathcal{Solution}\)

  很套路地建立树模型,对于 \(i\),连向最小地使得 \(a_i<a_j\)\(j\),那么 \(n\) 个结点构成一片森林。再根据 LGIS 的定义,一个结点若存在于区间,则以其子树内任意一点开头的 LGIS 的长度都会 \(+1\)。故只需要在 DFN 上维护线段树即可动态更新每个区间的答案。

  还有呢,联想到这道题,令 \(i\) 的 DFN 为 \(n-i+1\) 即可,树并不需要建出来 owo!

\(\mathcal{Code}\)

/* 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;
}
posted @ 2020-12-07 16:55  Rainybunny  阅读(68)  评论(0编辑  收藏  举报