zoukankan      html  css  js  c++  java
  • CF568E Longest Increasing Subsequence 题解

    CF568E Longest Increasing Subsequence

    首先重复填数对答案没有影响(,)所以先忽略这个条件(.)

    (f_i)为 以i为结尾的LIS的长度(,) (g_i) 为以i为结尾的LIS的上一位(.)

    (Min_x)为 当前长度为(x)的LIS的最小的结尾 (pos_x)当前长度为(x)的LIS的最小的结尾的位置(.)

    这些都可以简单(dp)出来(.)

    然后我们考虑怎么构造方案(.)

    不是(-1)的位置(x)我们可以直接跳到(g_x) (.)

    如果(x)所在的位置是(-1,)那么我们优先找(a_y ≠ -1 ,)(a_y<a_x,f_y=)当前的长度(-1,)那么我们就跳到位置(y.)

    否则(,)我们就只能跳到最近的一个(-1)的位置(.)

    (O(nlog n+mlog m+(n+m)k))

    代码(:)

    #include <bits/stdc++.h>
    using namespace std;
    template <typename T> void read(T &x){
    	x = 0; int f = 1; char ch = getchar();
    	while (!isdigit(ch)) {if (ch == '-') f = -1; ch = getchar();}
    	while (isdigit(ch)) {x = x * 10 + ch - '0'; ch = getchar();}
    	x *= f;
    }
    inline void write(int x){if (x > 9) write(x/10); putchar(x%10+'0'); }
    const int N = 100005,M = 100005,INF = 1e9 + 9;
    int mn[N],pos[N],mx;
    int n,a[N],f[N],g[N],m,b[M];
    int main(){
    	register int i,j,p;
    	read(n); for (i = 1; i <= n; ++i) read(a[i]),mn[i] = INF; a[++n] = INF-1; mn[n] = INF;
    	read(m); for (i = 1; i <= m; ++i) read(b[i]); sort(b+1,b+m+1);
    	for (i = 1; i <= n; ++i){
    		if (a[i] != -1){
    			p = lower_bound(mn,mn+mx+1,a[i]) - mn; if (p > mx) ++mx;
    			if (a[i] < mn[p]) mn[p] = a[i],pos[p] = i;
    			f[i] = p,g[i] = pos[p-1]; continue;
    		}
    		for (p = mx+1,j = m; j ; --j){
    			while (p && b[j] <= mn[p-1]) --p;
    			if (b[j] < mn[p]) mn[p] = b[j],pos[p] = i;
    		}
    		f[i] = -1; if (pos[mx+1]) ++mx;
    	}
    	int now = n,nowlen = f[n],nowv = a[n];
    	while (nowlen){
    		if (a[now] != -1){ --nowlen,nowv = a[now],now = g[now]; continue; }
    		for (i = m; i ; --i) if (b[i] != -1 && b[i] < nowv){ a[now] = b[i]; b[i] = -1; break; }
    		for (i = now-1; i ; --i) if (f[i] == nowlen-1 && a[i] < a[now]){ g[now] = i; break; }
    		if (!g[now]) for (i = now-1; i ; --i) if (a[i] == -1){ g[now] = i; break; }
    		--nowlen,nowv = a[now],now = g[now];
    	}
    	for (i = 1; i <= n; ++i) if (a[i] == -1)
    	for (j = 1; j <= m; ++j) if (b[j] != -1){ a[i] = b[j]; b[j] = -1; break; }
    	for (i = 1; i < n; ++i) write(a[i]),putchar(i<n?' ':'
    ');
    	return 0;
    }
    
  • 相关阅读:
    java 编译
    MapReduce
    搜索引擎中index、attribute和summary概念
    正排索引和倒排索引简单介绍
    SVN 使用
    PlantUML + Chrome 联合使用
    vim 多标签和多窗口
    关于数据库不适合docker的原因(摘抄)
    跨域
    is_valid校验机制
  • 原文地址:https://www.cnblogs.com/s-r-f/p/13581362.html
Copyright © 2011-2022 走看看