1 条题解

  • 1
    @ 2024-11-3 21:26:29
    #include<bits/stdc++.h>
    using namespace std;
    const int N=200009;
    int n; 
    int a[N];
    void input(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;++i)scanf("%d",&a[i]);
    }
    int as[N];
    void compress(){
    	int j=1;
    	for(int i=2;i<=n;++i)
    		if(a[i]!=a[j]) a[++j]=a[i];
    	n=j;
    	for(int i=1;i<=n;++i) as[i]=a[i];
    	sort(as+1,as+1+n);
    	int nUnq=unique(as+1,as+1+n)-(as+1); 
    	for(int i=1;i<=n;++i) 
    		a[i]=lower_bound(as+1,as+1+nUnq,a[i])-as;
    }
    int f[5009][5009];
    void solveDP(){	
    	for(int i=1;i<=n;++i)
    		for(int j=1;j<=n;++j)f[i][j]=0;
    	for(int i=2;i<=n;++i)
    		for(int j=1;j<=i-1;++j)if(a[j]!=a[i]){
    			f[i][j]=2;
    			for(int k=1;k<=j-1;++k)if(a[k]!=a[i]&&a[k]!=a[j])
    				f[i][j]=max(f[i][j],f[j][k]+1);
    		}
    	int ans=1; 
    	for(int i=2;i<=n;++i)
    		for(int j=1;j<=i-1;++j)
    			ans=max(ans,f[i][j]);
    	printf("%d\n",ans);	
    }
    /*
    压缩后:邻居都不同
    离散化:数值变小
     
    g[i][x]表示i号结尾的合法子序列最长长度
    倒数第二位是pre[i][x]位置的元素 
    lastPos[v]表示数值v在当前访问的位置[1,2,..,i]内最后出现的位置 
    候选人容器中只考虑各个数值最后出现的位置,最多5个位置候选人
    */
    int g[N][10];
    int pre[N][10]; 
    int lastPos[N];
    const int C=5;
    void solve(){
    	for(int i=1;i<=n;++i)
    		for(int j=0;j<=C;++j)g[i][j]=0;
    	for(int i=1;i<=n;++i)lastPos[i]=0;
    	set<int> PRE;
    	set<int>::iterator it; 
    	for(int i=1;i<=n;++i){
    		while(PRE.size()>5)
    			PRE.erase(PRE.begin());
    		int cnti=0;
    		for(it=PRE.begin();it!=PRE.end();++it)
    			pre[i][++cnti]=*it;
    		it=PRE.find(lastPos[a[i]]);
    		if(it!=PRE.end()) PRE.erase(it);
    		PRE.insert(i);
    		lastPos[a[i]]=i;
    	}
    	for(int i=2;i<=n;++i)
    		for(int pi=1;pi<=C;++pi){
    			int j=pre[i][pi];
    			if(!j)break;
    			if(a[i]==a[j])continue;
    			g[i][pi]=2;
    			for(int pj=1;pj<=C;++pj){
    				int k=pre[j][pj];
    				if(!k)break;
    				if(a[i]==a[k]||a[j]==a[k])continue;
    				g[i][pi]=max(g[i][pi],g[j][pj]+1);
    			}
    		}	
    	int ans=1;
    	for(int i=2;i<=n;++i)	
    		for(int pi=1;pi<=C;++pi){
    			int j=pre[i][pi];	
    			if(!j)break;
    			if(a[i]==a[j])continue;
    			ans=max(ans,g[i][pi]);
    		}
    	printf("%d\n",ans);		
    }
    int main(){
    	freopen("admission.in","r",stdin);
    	freopen("admission.out","w",stdout);
        int t;
    	cin>>t;
    	int sN=0; 
        while(t--){
    		input();
    		compress();	
    		sN+=n;
    		if(sN<=500)
    			solveDP();
    		else
    			solve();
    	}
    	return 0;
    }
    
    
    
    

    • 1

    信息

    ID
    6
    时间
    2000ms
    内存
    256MiB
    难度
    8
    标签
    递交数
    2
    已通过
    1
    上传者