Solution -「CF 1132G」Greedy Subsequences
阿新 • • 發佈:2020-12-07
\(\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; }