题目:http://poj.org/problem?id=3320
题意:给定N个元素的数组,找出最短的一段区间使得区间里面的元素种类等于整个数组的元素种类。
分析:暴力枚举区间的起点x,然后找到最小的y,使得区间[x,y]满足条件,x向有移位后变成x',现在的y'肯定不至于在y的左边。存状态的话map和hash都可以。
map代码:
#include <iostream>
#include <set>
#include <map>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 1e6+6;
int a[maxn],t[maxn];
int main()
{
map <int ,int > mp;
int n,i,j,ncase;
while(scanf("%d",&n)!=EOF)
{
for(i=1;i<=n;i++)
{
scanf("%d",&a[i]);
t[i-1]=a[i];
}
mp.clear();
sort(t,t+n);
int Kind=unique(t,t+n)-t;
int ans=n;
int R=1;
for(int L=1;L<=n;L++)
{
while(R<=n && mp.size()<Kind)
{
if(mp.find(a[R])==mp.end())
mp.insert(make_pair(a[R],1));
else
++mp[a[R]];
R++;
}
if(mp.size()<Kind)
break;
if(R-L<ans)
ans=R-L;
if(mp[a[L]]==1)
mp.erase(mp.find(a[L]));
else
--mp[a[L]];
}
printf("%d\n",ans);
}
return 0;
}
hash代码:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define ABS(x) (x>0?x:-x)
const int maxn = 1e6+7;
int a[maxn],N;
struct node
{
int value,num;
int next;
};
int Table[maxn],cnt;
node List[maxn];
int FindKind()
{
cnt=0;
memset(Table,-1,sizeof(Table));
int ret=0,hash,fd;
for(int i=0;i<N;i++)
{
hash=ABS(a[i])%maxn;
fd=0;
hash=Table[hash];
while(hash!=-1)
{
if(List[hash].value==a[i])
{
fd=1;
break;
}
hash=List[hash].next;
}
if(fd)
continue;
hash=ABS(a[i])%maxn;
List[cnt].value=a[i];
List[cnt].next=Table[hash];
Table[hash]=cnt++;
ret++;
}
return ret;
}
int Insert(int v)
{
int hash=ABS(v)%maxn;
hash=Table[hash];
while(hash!=-1)
{
if(List[hash].value==v)
return List[hash].num++;
hash=List[hash].next;
}
hash=ABS(v)%maxn;
List[cnt].value=v;
List[cnt].num=1;
List[cnt].next=Table[hash];
Table[hash]=cnt++;
return 0;
}
int Delete(int v)
{
int hash=ABS(v)%maxn;
hash=Table[hash];
while(hash!=-1)
{
if(List[hash].value==v)
return List[hash].num--;
hash=List[hash].next;
}
return 0;
}
int main()
{
int i,j;
int ncase;
scanf("%d",&ncase);
while(ncase--)
{
scanf("%d",&N);
for(i=0;i<N;i++)
scanf("%d",&a[i]);
int Kind=FindKind();
memset(Table,-1,sizeof(Table));
cnt=0;
int R=0,ans=N,sz=0;
for(int L=0;L<N;L++)
{
while(R<N && sz<Kind)
{
if(!Insert(a[R]))
sz++;
R++;
}
if(sz<Kind)
break;
if(R-L<ans)
ans=R-L;
if(Delete(a[L])==1)
sz--;
}
printf("%d\n",ans);
}
return 0;
}