• 【CodeForces 261D】Maxim and Increasing Subsequence


    链接:

    洛谷

    博客园

    题目大意:

    将长度为 (n)(b) 数组复制 (t),首尾相连后得到 (a) 数组,求 (a) 的最长上升序列长度。

    正文:

    如果 (t) 足够大,答案是固定的。设 (cnt) 表示 (b) 数组不同数字个数,则显然有当 (cntleq t) 时答案是 (cnt)

    再考虑 (cnt>t) 的情况。跑一趟 (O(n^2t^2)) 的最长上升子序列显然不可能,考虑优化它。设 (f_i) 表示 (a) 数组中第 (i) 个数在最长上升序列的最长长度。则有:

    [f_i=max_{j<i,a_j<a_i}{f_i+1} ]

    其中 (max) 可以用树状数组维护。

    还有一点,空间 (O(nt)) 是接受不了的,考虑滚动数组,滚到 (O(n)) 就行了。

    代码:

    int k, t, n, maxb, cnt;
    bool a[N];
    
    int tr[N], f[N], b[N];
    
    void update(int x, int val)
    {
    	for (; x <= maxb; x += x & -x) tr[x] = max(tr[x], val);
    	return;
    }
    
    int query(int x)
    {
    	int ans = 0;
    	for (; x; x -= x & -x) ans = max(ans, tr[x]);
    	return ans;
    }
    
    int ans;
    
    int main() 
    {
        for (scanf("%d%d%d%d", &k, &n, &maxb, &t); k--; )
        {
        	ans = 0;
        	memset (a, 0, sizeof a);
        	memset (b, 0, sizeof b);
        	memset (tr, 0, sizeof tr);
        	memset (f, 0, sizeof f);
        	cnt = 0;
        	for (int i = 1; i <= n; i++)
        	{
        		scanf ("%d", &b[i]);
        		if (!a[b[i]]) cnt++, a[b[i]] = 1;
    		}
    		if (cnt <= t) {printf ("%d
    ", cnt); continue;} 
    		for (int j = 1; j <= t; j++)
    			for (int i = 1; i <= n; i++)
    			{
    				int tmp = query(b[i] - 1) + 1;
    				if (tmp > f[i])
    				{
    					f[i] = tmp;
    					update(b[i], tmp);
    					ans = max (ans, tmp);
    				}
    			}
    		printf ("%d
    ", ans);
    	}
        return 0;
    }
    
  • 相关阅读:
    Computability 2: Gödel Number
    Computability 1: Computational Models
    Axiomatic Set Theory
    External Sorting Model
    Minimum Spanning Tree
    All-Pairs Shortest Paths
    Python 泰坦尼克生存率预测(修改)
    Python 分析Kaggle_Titanic案例
    Python 北京二手房成交数据分析过程
    数据挖掘主要解决的四类问题以及常用到的算法
  • 原文地址:https://www.cnblogs.com/GJY-JURUO/p/14316871.html
Copyright © 2020-2023  润新知