zoukankan      html  css  js  c++  java
  • 【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;
    }
    
  • 相关阅读:
    机器学习:特征选择方法简介
    VS快捷键
    非常适用的Sourceinsight插件,提高效率【强力推荐】
    Linux静态库和共享库
    C/C++ 位域知识小结
    __BEGIN_DECLS 和 __END_DECLS
    C语言可变参数va_list
    mac的terminal快捷键
    linux进程、线程与cpu的亲和性(affinity)
    C++ Singleton (单例) 模式最优实现
  • 原文地址:https://www.cnblogs.com/GJY-JURUO/p/14316871.html
Copyright © 2011-2022 走看看