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