poj3320 快排离散

题目要求求出包含所有ideas的最段序列,如果整数的范围很小的话就简单了,但是这个题目中idea可能很大,因此无法直接用数的大小对应下标

所以必须离散化才可以,因为数一共有1000000,所以最大编号最大为1000000,利用快排离散。

m[i]为原始数据,s[i]为压缩后每个idea对应的编号,index[i]为每个编号出现的下标,其实这个题就是之前遇到的那个求包含给定字符集的最短子串是一个问题,只是这个题目多了一个离散。

源代码:

#include <iostream>
#include <algorithm>
#include <stdio.h>
using namespace std;
const int N=1000000;
const int INF=1000001;
int m[N],s[N],index[N],n;
int cmp(const void *a1,const void *a2)
{
return *((int *)a1) - *((int *)a2);
}
int getID(int data,int len)
{
int i=0,j=len-1;
while(i<=j)
{
int mid=(i+j)>>1;
if(data == s[mid])
return mid;
else if(data < s[mid])
j=mid-1;
else
i=mid+1;
}
return -1;
}
int getNextIdx(int midx,int k,int len)
{
int j,rs=k;
for(int i=midx+1;i<k;i++)
{
j=getID(m[i],len);
if(index[j]<rs)
{
rs=index[j];
}
}
return rs;
}

int main()
{
int i,j,k,num,cnt,minIdx,ans;
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%d",&m[i]);
s[i]=m[i];
}
qsort(s,n,sizeof(int),cmp);
j=0;
for(i=0;i<n;i=k)
{
k=i;
while(s[k]==s[i])
k++;
s[j++]=s[i];//存放m[i]对应的是压缩后的第几个编号
}
num=j;
memset(index,-1,sizeof(index));//存放每个压缩后的每个编号对应出现的下标
// for(i=0;i<j;i++)
// printf("%d ",s[i]);
// cout<<"num"<<num<<endl;
cnt=0;
minIdx=0;
ans=INF;
for(i=0;i<n;i++)
{
j=getID(m[i],num);
if(-1 == index[j])
{
index[j]=i;
cnt++;
}
else
{
if(m[minIdx] != m[i])
{
index[j]=i;
}
else
{
minIdx=getNextIdx(minIdx,i,num);
index[j]=i; //忘记更新了
// cout<<minIdx<<endl;
}
}
if(cnt == num)
{
if(ans > (i - minIdx +1))
ans=i - minIdx +1;
}
// cout<<ans<<endl;
}
printf("%d\n",ans);
return 0;
}



原文地址:https://www.cnblogs.com/buptLizer/p/2190186.html