您的位置:首页 > 编程语言

UVa 11572

2015-07-20 11:30 337 查看
题目:输入一个长度为n的序列A,找到一个尽量长的连续子序列,使得该序列中没有相同的元素。

代码:

方法一

#include<iostream>
#include<set>
#include<algorithm>
#define max(a,b) ((a)>(b)?(a):(b))
using namespace std;

const int Max=1000000+5;
int A[Max];

int main(){
int T;
while(cin>>T){
while(T--){
int n;
cin>>n;
for(int i=0;i<n;i++){
cin>>A[i];
}

set<int> s;
int L=0,R=0,ans=0;
while(R<n){
while(R<n&&!s.count(A[R])){
s.insert(A[R++]);
}

ans=max(ans,R-L);

s.erase(A[L++]);
}
cout<<ans<<endl;
}
}
return 0;
}

方法二

#include<iostream>
#include<map>
#define max(a,b) ((a>b)?(a):(b))
using namespace std;

const int Max=1000000+5;
int a[Max],last[Max];
map<int,int> cur;

int main(){
int T;
while(cin>>T){
while(T--){
int n;
cin>>n;
for(int i=0;i<n;i++){
cin>>a[i];
if(!cur.count(a[i])) last[i]=-1;
else last[i]=cur[a[i]];
cur[a[i]]=i;
}

int L=0,R=0,ans=0;
while(R<n){
while(R<n&&last[R]<L){
R++;
}
ans=max(ans,R-L);

L++;
}

cout<<ans<<endl;
cur.clear();
}
}
return 0;
}

 

分析:以上是书(算法竞赛经典入门)中的两中解决方法,方法一用的是集合容器来解决重复问题,方法二使用的是存储下标来处理重叠。可见使用适合的数据结构不仅能简化代码,还能高效地解决问题。

借助这些作为启发,我对后面的一道题进行了解答。

题目是:输入一个正整数k和一个长度为n的整数序列,定义f(i)表示从元素i开始的连续k个元素的最小值,从f(i开始一直到f(n-k+1)输出。

这个题在书上作为思考题是没有答案的,以下是我的代码:

#include<iostream>
#include<cstdio>
#include<memory.h>
using namespace std;
const int Max=1000+5;

int main(){
int T;
while(cin>>T){
while(T--){
int a[Max],b[Max];
int n,k;
cin>>n>>k;
for(int i=0;i<n;i++){
cin>>a[i];
}
memset(b,0,sizeof(b));
int front,rear,num=0;
for(int j=0;j<k;j++){
if(b[0]==0) b[0]=a[j];
else{
if(a[j]<b[0]){
b[0]=a[j];
for(int j=1;j<num;j++) b[j]=0;
num=0;
}else if(a[j]>b[num]&&b[num]!=0) b[++num]=a[j];
}
}
cout<<b[0]<<endl;
front=0;rear=k-1;
while(rear<n-1){
if(a[front]==b[0]){
for(int i=0;i<num;i++)
b[i]=b[i+1];
num--;
}
front++;
if(a[rear+1]>b[num]){
b[++num]=a[rear+1];

4000
}else{
if(a[rear+1]<b[0])
{
for(int i=0;i<=num;i++) b[i]=0;
b[0]=a[rear+1];
num=0;
}
}
rear++;
cout<<b[0]<<endl;
}
}
}
return 0;
}

这道题采用的是滑动窗口的形式来改变范围,并使其进入准备好的单调序列。正是因为不知道最小值什么时候被丢出序列,所以要保存好上一状态的单调序列。其时间复杂度比理想的O(n)大(此处没有使用书上建议的单调队列,考虑到内存问题,用时间去换内存),但是比每次检索最小值的复杂度O((n-k)log(k))一般要小。

 

如有疑问或对代码的改进有建议,请给我留言,谢谢。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  代码 小白