| ||||||||||
| Online Judge | Problem Set | Authors | Online Contests | User | ||||||
|---|---|---|---|---|---|---|---|---|---|---|
| Web Board Home Page F.A.Qs Statistical Charts | Current Contest Past Contests Scheduled Contests Award Contest | |||||||||
郁闷了,自己测了好几组数据都是对的,但提交老是WA,达人们过来看看。程序附上了详细的注释。。。#include <stdio.h>
#include <iostream>
#include <math.h>
#include <algorithm>
using namespace std;
#define MAX 1000005
#define NMAX 1000005
long a[NMAX];//输入的数组
long chuli[NMAX];//将输入的数组a[]置入,进行排序
long youxu[NMAX];
//将排序好的chuli[],剔除重复的数字后,
//放入该数组,以后对某个数的查找,都依赖该数组
long tiao[NMAX];//tiao[i],第i位的数是否重复出现,若是,下次可跳过
long finded[NMAX];
//还未找到所有数字时使用,find[i]=1表示某个数在youxu[]数组中对应的下标为i时,找到了这个数
long chongfu[NMAX];//同一数字的最后一个所指的下标
long f[NMAX];//f[i],以第i个数为终点,最短符合条件的子串的长度
bool cmd(long a,long b)
{
return a<b;
}
long find(long num,long da)
{ //在youxu[]数组中查找num所对应的下标,其中da是youxu[]数组的大小
long low,high,mid;
low=1;high=da;
mid=(low+high)/2;
while(low<high)
{
if(youxu[mid]==num) return mid;
else if(youxu[mid]<num) low=mid+1;
else high=mid-1;
mid=(low+high)/2;
}
return mid;
}
long init(long num)
{
long i,j;
sort(chuli,chuli+num,cmd);
youxu[1]=chuli[1];
j=1;
for(i=1;i<num;i++)
{//将排好序的chuli[]数组中不重复的数放入youxu[]数组
if(chuli[i]!=chuli[i+1]) youxu[++j]=chuli[i+1];
}
return j;//youxu[]的数组大小
}
void prlong(long num,long ci)
{ //这个子函数用来调试时打印tiao[],chongfu[],f[]的状态
long i,j,k;
cout<<ci<<endl;
for(i=1;i<=num;i++) printf("%2d",i);
cout<<endl;
cout<<"this tiao"<<endl;
for(i=1;i<=num;i++)
printf("%2d",tiao[i]);
cout<<"\nthis is chongfu"<<endl;
for(j=1;j<=num;j++)
printf("%2d",chongfu[j]);
cout<<endl;
cout<<"this is f"<<endl;
for(k=1;k<=num;k++)
printf("%2d",f[k]);
cout<<endl;
}
long solve(long tnum)
{
long first,flag,i,j,findnum=0,im,num,min;
first=-1;//first为符合条件的子串最开始的位置
flag=0;
min=MAX;
sort(chuli+1,chuli+1+tnum,cmd);
num=init(tnum);//构造一个升序的非重复的序列
memset(finded,0,sizeof(finded));
memset(chongfu,0,sizeof(chongfu));
memset(tiao,0,sizeof(tiao));
memset(f,0,sizeof(f));
for(i=1;i<=tnum;i++)
{
if(flag==0)
{//还未有全部数字出现时
if(findnum<num)
{
im=find(a[i],num);//找出a[i]在youxu[]数组中的下标,下同
if(finded[im]==0)
{//这个数字之前未出现
findnum++;
finded[im]=1;
}
else
{//之前出现了
tiao[chongfu[im]]=1;//原来的位置要置为跳过的标记
}
chongfu[im]=i;//该数字最后出现时的下标
if(findnum==num)
{//全部数字刚好都出现了
flag=1;
f[i]=i;//从这里开始,以后的过程才能置f[]
min=i;
j=1;
while(tiao[j]==1) j++;
first=j;//找到最开始的子串的初始位置
}
}
}
else
{//全部数字已经都出现了,也就是出现了题目中需要的子串
if(a[i]==a[first])
{ //如果新出现的数跟之前子串最开始的数一样
tiao[first]=1;
im=find(a[i],num);
//first要一直往后跳到没有重复数字出现的地方
first++;
while(tiao[first]==1) first++;
chongfu[im]=i;//这是该数最后出现的位置,其实也就是当前位置
}
else
{//置之前出现的重复的数所对应的tiao
im=find(a[i],num);
tiao[chongfu[im]]=1;
chongfu[im]=i;//这是该数最后出现的位置,其实也就是当前位置
}
f[i]=i-first+1;//子串长度
if(f[i]<min) min=f[i];
}
// cout<<"first="<<first<<endl;
// prlong(tnum,i);
}
return min;
}
int main()
{
long tnum,i;
scanf("%ld",&tnum);
for(i=1;i<=tnum;i++)
{
scanf("%ld",&a[i]);
chuli[i]=a[i];
}
cout<<solve(tnum)<<endl;
return 0;
}
Followed by: Post your reply here: |
All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator