终于过了,发篇题解庆祝一下
实际上是为了不让后人没一篇优秀的题解看
进入正题
实际上是我懒得打了
emmmm,怎么这么多实际上QAQ?
不管啦,看题,我们将相同的数作为一个区间存下来
将两个的坐标分别作为区间的左右端点
然后我们发现
如果有一个区间包含了另一个区间,那么!!!
就可以删掉那个较大的区间,是不是很神奇!是不是!是不是!
咳咳,言归正传,那么我们们在边读边做时就会自动的将区间按左端点从小到大排序
由上可知,右端点也是有序的
在每次询问时,我们可以二分一个查找,找到可以得出答案的范围
在其中找最小的区间长度,就可以啦~~~
上面的一步可以用RMQ哦QAQ
注意:当我们找出的l和r有l>r时,就输出-1啦
丢代码:
#includeusing namespace std;int n,m;int a[500001],d[500001],cnt;int logg[500001];int f[500001][40];int l[500001],r[500001];map mp;//第一个是原值,第二个是原值的位置inline int min(int a,int b){ return a ='0'&&ch<='9')) { if(ch=='-') w=1; ch=getchar(); } while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=getchar(); return w?-x:x;}int main(){ n=read(); m=read(); for(register int i=1;i<=n;++i) { a[i]=read(); if(mp.count(a[i])) { int j=mp.find(a[i])->second; mp[a[i]]=i; if(!cnt) l[++cnt]=j,r[cnt]=i,d[cnt]=i-j; else if(l[cnt]>=j) continue; else l[++cnt]=j,r[cnt]=i,d[cnt]=i-j; } else mp.insert(make_pair(a[i],i)); } logg[0]=-1; for(register int i=1;i<=cnt;++i) f[i][0]=d[i],logg[i]=logg[i>>1]+1; for(register int j=1;(1< <=cnt;++j) for(register int i=1;i+(1< <=cnt;++i) f[i][j]=min(f[i][j-1],f[i+(1<