• CF261D Maxim and Increasing Subsequence


    LXXXIII.CF261D Maxim and Increasing Subsequence

    首先,我们可以发现,当这个重复次数很大的时候,答案就等于序列中出现的不同权值个数。实际上,这个“很大”就可以被当作“大于等于不同权值个数”。

    不同权值个数实际上是\(\min(n,m)\)级别的,其中\(n\)是序列长度,\(m\)是序列最大值。因此直接特判掉即可。

    我们考虑暴力DP。设\(f_{i,j}\)表明现在跑到序列中的第\(i\)个位置,且所有最后一个数小于等于\(j\)的LIS的长度的最大值。假如我们直接暴力扫过DP数组更新的话,最多最多更新\(\min(n,m)^2\)次,即最终把DP数组中所有数全都更新到最大值。而又有\(n\times m\leq2\times10^7\),所以我们最终会发现复杂度最大只有\(2\times10^7\)。时限\(6\)秒,轻松跑过。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    int T,n,lim,m,a[100100],f[100100];
    vector<int>v;
    int main(){
    	scanf("%d%d%d%d",&T,&n,&lim,&m);
    	while(T--){
    		v.clear();
    		for(int i=0;i<n;i++)scanf("%d",&a[i]),v.push_back(a[i]);
    		sort(v.begin(),v.end()),v.resize(unique(v.begin(),v.end())-v.begin());
    		if(v.size()<=m){printf("%d\n",v.size());continue;}
    		for(int i=0;i<n;i++)a[i]=lower_bound(v.begin(),v.end(),a[i])-v.begin()+1;
    		for(int i=1;i<=v.size();i++)f[i]=0;
    		for(int i=0;i<n*m;i++){
    			int now=f[a[i%n]-1]+1;
    			for(int j=a[i%n];j<=v.size();j++)if(f[j]<now)f[j]=now;else break;
    			if(f[v.size()]==v.size())break;
    		}
    		printf("%d\n",f[v.size()]);
    	}
    	return 0;
    }
    

  • 相关阅读:
    1.1.28 文字所在段落增加下划线
    Microsoft Project 2010基础使用方法
    16.3 将Win7文档的内容到复制Linux的vi中
    3.4 在Word中的公式和序号之间填充连续的点
    18.25 JLink调试程序步骤
    18.24 Ubuntu修改静态IP
    18.23 inline函数功能
    18.22 sprintf函数功能
    18.21 关键字extern
    18.20 频率单位转换
  • 原文地址:https://www.cnblogs.com/Troverld/p/14598508.html
Copyright © 2020-2023  润新知