Wave (dp/暴力)

Wave

Avin is studying series. A series is called "wave" if the following conditions are satisfied:
1) It contains at least two elements;
2) All elements at odd positions are the same;
3) All elements at even positions are the same;
4) Elements at odd positions are NOT the same as the elements at even positions.
You are given a series with length n. Avin asks you to find the longest "wave" subseries. A subseries is a subsequence of a series.

Input

The first line contains two numbers n, c (1 ≤ n ≤ 100, 000, 1 ≤ c ≤ 100). The second line contains n integers whose range is [1, c], which represents the series. It is guaranteed that there is always a "wave" subseries.

Output

Print the length of the longest "wave" subseries.

Sample Input

5 3
1 2 1 3 2

Sample Output

4

这道题的题意是在给定的区间可以找到的最长的ababababababab。。。的序列长度。

首先代码最简洁的dp

#include<iostream>

using namespace std;
int vis[110];
int dp[110][110];
int main(){
	int n,c,t;
	cin>>n>>c;
//	memset(s,0,sizeof(s));
	for(int i=0;i<n;i++){
		cin>>t;
		for(int j=1;j<=c;j++){
			if(vis[j]>vis[t]){
				dp[j][t]=dp[t][j]+1;
			}
		}
		vis[t]=i+1;
	}
	int ans=0;
	for(int i=1;i<=c;i++){
		for(int j=1;j<=c;j++){
//			cout<<dp[i][j]<<" ";
			ans=max(ans,dp[i][j]);
		}
//		cout<<endl;
	}
	cout<<ans+1<<endl;
	return 0;
}

然后是暴力(用vector存序列,然后每两个两个求他们的最长合法序列)以下代码会超时,需要改成scanf。。

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int n,c;
typedef pair<int,int> p;
vector<p> ve[110];
int cmp(p a,p b){
	return a.first<b.first;
}
int main(){
	cin>>n>>c;
	for(int i=1;i<=n;i++){
		int x;
		cin>>x;
		ve[x].push_back(p(i,x));
	}
	int maxn=0;
	for(int i=1;i<=c;i++){
		for(int j=1;j<=c;j++){
			if(ve[i].size()&&ve[j].size()){//两个都在序列中出现
			vector<p> v;
			for(int z=0;z<ve[i].size();z++){
				v.push_back(ve[i][z]);
			} 
			for(int z=0;z<ve[j].size();z++){
				v.push_back(ve[j][z]);
			} 
			sort(v.begin(),v.end(),cmp);
			int sum=0,flag;
			for(int z=0;z<v.size();z++){
				if(z==0){
					sum++;
					flag=v[z].second;
				}
				else if(v[z].second!=flag){
					sum++;
					flag=v[z].second;
				}
			}
			maxn=max(maxn,sum); 
			}
		}
	}
	cout<<maxn<<endl;
	return 0;
}

更暴力的只用一个vector (感觉更好理解也更快)

就是每隔一个不同的消耗一个,序列长度加一。

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int n,c;
//typedef pair<int,int> p;
vector<int> ve[110];
//int cmp(p a,p b){
//	return a.first<b.first;
//}
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	cin>>n>>c;
	for(int i=1;i<=n;i++){
		int x;
		cin>>x;
		ve[x].push_back(i);
	}
	int maxn=0;
	for(int i=1;i<=c;i++){
		for(int j=1;j<=c;j++){
			if(i==j) continue;//相等的不是合法波 
			int x2=0,x1=0,now=0,sum=0;//now标记此时遍历的位置,sum标记此时序列的长度 
			while(1){
				while(ve[i][x1]<now&&x1<ve[i].size()) x1++;
				now=ve[i][x1];
				if(x1==ve[i].size()) break;
				sum++;
				while(ve[j][x2]<now&&x2<ve[j].size()) x2++;
				now=ve[j][x2];
				if(x2==ve[j].size()) break;
				sum++;
 			}
			maxn=max(maxn,sum);
			
		}
	}
	cout<<maxn<<endl;
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值