传送门
把珠子按位置排序
当
i
=
1
i=1
i=1时,
p
o
s
[
a
[
i
]
.
c
]
pos[a[i].c]
pos[a[i].c]为
−
1
-1
−1,那么
a
[
i
]
a[i]
a[i]入队,
+
+
c
t
++ct
++ct
更新
p
o
s
[
a
[
i
]
.
c
]
pos[a[i].c]
pos[a[i].c]的值为
a
[
i
]
.
p
a[i].p
a[i].p
当队头
h
<
=
i
h<=i
h<=i且队头的元素所在位置
a
[
h
]
.
p
a[h].p
a[h].p不等于该位置珠子最后出现的位置时出队。
当
c
t
ct
ct=
k
k
k时更新答案
a
n
s
=
m
i
n
(
a
n
s
,
a
[
i
]
.
p
−
a
[
h
]
.
p
)
ans=min(ans,a[i].p-a[h].p)
ans=min(ans,a[i].p−a[h].p)
从头枚举到尾就好了,时间复杂度
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn),其实还有
O
(
n
l
o
g
k
)
O(nlogk)
O(nlogk)的做法。
#include<bits/stdc++.h>
#define il inline
using namespace std;
const int N=1e6+5;
#define getchar()(p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[1<<21],*p1=buf,*p2=buf;
il int read(){
int x=0,f=1;char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=getchar()) x=(x+(x<<2)<<1)+c-48;
return x*f;
}
struct A{int c,p;}a[N];
int n,k,ans,pos[N],m,h=1,ct;
il bool cmp(A x,A y){return x.p<y.p;}
int main(){
n=read(),k=read();
for(int i=1,x;i<=k;++i){
x=read();pos[i]+=x;
for(int j=1;j<=x;++j) a[++m].p=read(),a[m].c=i;
}
sort(a+1,a+n+1,cmp);
ans=a[n].p-a[1].p;
memset(pos,-1,sizeof(pos));
for(int i=1;i<=n;++i){
if(pos[a[i].c]==-1) ++ct;
pos[a[i].c]=a[i].p;
while(h<=i&&a[h].p!=pos[a[h].c]) ++h;
if(ct==k&&a[i].p-a[h].p<ans) ans=a[i].p-a[h].p;
}
return !printf("%d",ans);
}