Description: D e s c r i p t i o n :
小西有一条很长的彩带,彩带上挂着各式各样的彩珠。已知彩珠有N个,分为K种。简单的说,可以将彩带考虑为x轴,每一个彩珠有一个对应的坐标(即位置)。某些坐标上可以没有彩珠,但多个彩珠也可以出现在同一个位置上。 小布生日快到了,于是小西打算剪一段彩带送给小布。为了让礼物彩带足够漂亮,小西希望这一段彩带中能包含所有种类的彩珠。同时,为了方便,小西希望这段彩带尽可能短,你能帮助小西计算这个最短的长度么?彩带的长度即为彩带开始位置到结束位置的位置差。
Solution:
S
o
l
u
t
i
o
n
:
不错的题,有很多种解法,本菜今天xjb yy出了好像比较新鲜的做法
首先维护
L,R
L
,
R
表示现在的区间
[L,R]
[
L
,
R
]
是满足”包含所有种类彩珠” 的某个区间
对于每个彩珠,记录同样是这个种类的彩珠下一次出现的位置
next[i]
n
e
x
t
[
i
]
,那么若现在弹出第
x
x
个彩珠(左指针右移过了),我们将右指针的范围移到
max(R,next[x])
m
a
x
(
R
,
n
e
x
t
[
x
]
)
就可以保证新区间依然满足题目条件
实现很简单,先排序在
O(n)
O
(
n
)
扫描即可,好像可以
k
k
<script type="math/tex" id="MathJax-Element-781">k</script>路归并但是懒得写了wwww
下面是代码:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#define LL long long
using namespace std;
const int maxn=1000000;
struct ball
{
int pos,nxt;
}a[maxn];
bool cmp(ball a,ball b)
{
return a.pos<b.pos;
}
int n,k,cnt=0,l=-1,r=-1,ans;
int col[maxn];
int main()
{
scanf("%d%d",&n,&k);
int ti;
for(int i=1;i<=k;++i)
{
ti=read();
for(int j=1;j<=ti;++j)
{
col[j]=read();
if(col[j]==col[j-1])ti--,j--;
}
col[ti+1]=0;
l=(l==-1?col[1]:min(l,col[1]));
r=(r==-1?col[1]:max(r,col[1]));
for(int j=1;j<=ti;++j)a[++cnt].pos=col[j],a[cnt].nxt=col[j+1];
}
sort(a+1,a+1+cnt,cmp);
ans=r-l;
for(int i=1;i<=cnt;++i)
{
if(!a[i].nxt)break;
r=max(r,a[i].nxt);
l=a[i+1].pos;
ans=min(ans,r-l);
}
printf("%d\n",ans);
}