[THOJ 2471] lis 最值字典序
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[THOJ 2471] lis 最值字典序相关的知识,希望对你有一定的参考价值。
题意
给定一个长度为 n 的序列 A .
问是否存在一个长度为 L 的上升子序列.
如果存在, 输出字典序最小的.
N <= 100000 .
分析
先按照 (key, pos) , 把上升子序列进行一些小小的转换, 变成选取坐标尽可能小的.
处理出以每个位置开头的上升子序列的长度.
然后贪心选取.
小结
对于最值字典序的问题, 我们通常有这样一些处理手段:
① 通过排序等方法, 将问题进行转化.
② 每次尽可能选最后, 能得到最大字典序. (反过来做, 能得到最小字典序)
③ 预处理每个位置开头的上升子序列的长度, 然后用某些数据结构来选取.
实现
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cctype> 5 #include <algorithm> 6 using namespace std; 7 #define F(i, a, b) for (register int i = (a); i <= (b); i++) 8 #define D(i, a, b) for (register int i = (a); i >= (b); i--) 9 inline int rd(void) { 10 int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == ‘-‘) f = -1; 11 int x = 0; for (; isdigit(c); c = getchar()) x = x*10+c-‘0‘; return x*f; 12 } 13 14 const int N = 100005; 15 16 int n, L; 17 struct Data { 18 int key, pos; 19 friend inline bool operator < (Data A, Data B) { return A.key != B.key ? A.key < B.key : A.pos < B.pos; } 20 }w[N]; 21 int f[N], tr[N]; 22 23 inline int lowbit(int i) { return i & -i; } 24 inline void Add(int x, int w) { for (int i = x; i <= n; i += lowbit(i)) tr[i] = max(tr[i], w); } 25 inline int Query(int x) { int Max = 0; for (int i = x; i > 0; i -= lowbit(i)) Max = max(Max, tr[i]); return Max; } 26 27 int main(void) { 28 #ifndef ONLINE_JUDGE 29 freopen("lis.in", "r", stdin); 30 #endif 31 32 n = rd(), L = rd(); 33 F(i, 1, n) w[i] = (Data){rd(), i}; 34 sort(w+1, w+n+1); 35 36 D(i, n, 1) { 37 f[i] = Query(n - w[i].pos + 1) + 1; 38 Add(n - w[i].pos + 1, f[i]); 39 } 40 41 if (*max_element(f+1, f+n+1) < L) puts("impossible"), 0; 42 for (int Last = -1, W = -1, i = 1; i <= n && L >= 1; i++) 43 if (f[i] >= L && Last < w[i].pos && W < w[i].key) 44 printf("%d ", w[i].key), L--, Last = w[i].pos, W = w[i].key; 45 puts(""); 46 47 return 0; 48 }
以上是关于[THOJ 2471] lis 最值字典序的主要内容,如果未能解决你的问题,请参考以下文章
bzoj千题计划141:bzoj3532: [Sdoi2014]Lis