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;
    }
    
  • 相关阅读:
    Security and Cryptography in Python
    Security and Cryptography in Python
    Security and Cryptography in Python
    Security and Cryptography in Python
    Security and Cryptography in Python
    Security and Cryptography in Python
    Security and Cryptography in Python
    微信小程序TodoList
    C语言88案例-找出数列中的最大值和最小值
    C语言88案例-使用指针的指针输出字符串
  • 原文地址:https://www.cnblogs.com/s-r-f/p/13581362.html
Copyright © 2011-2022 走看看