bzoj1293[SCOI2009]生日礼物 尺取法
1293: [SCOI2009]生日礼物
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2838 Solved: 1547
[Submit][Status][Discuss]
Description
小西有一条很长的彩带,彩带上挂着各式各样的彩珠。已知彩珠有N个,分为K种。简单的说,可以将彩带考虑为x轴,每一个彩珠有一个对应的坐标(即位置)。某些坐标上可以没有彩珠,但多个彩珠也可以出现在同一个位置上。 小布生日快到了,于是小西打算剪一段彩带送给小布。为了让礼物彩带足够漂亮,小西希望这一段彩带中能包含所有种类的彩珠。同时,为了方便,小西希望这段彩带尽可能短,你能帮助小西计算这个最短的长度么?彩带的长度即为彩带开始位置到结束位置的位置差。
Input
第一行包含两个整数N, K,分别表示彩珠的总数以及种类数。接下来K行,每行第一个数为Ti,表示第i种彩珠的数目。接下来按升序给出Ti个非负整数,为这Ti个彩珠分别出现的位置。
Output
应包含一行,为最短彩带长度。
Sample Input
6 3
1 5
2 1 7
3 1 3 8
1 5
2 1 7
3 1 3 8
Sample Output
3
HINT
有多种方案可选,其中比较短的是1~5和5~8。后者长度为3最短。
【数据规模】
对于50%的数据, N≤10000;
对于80%的数据, N≤800000;
对于100%的数据,1≤N≤1000000,1≤K≤60,0≤彩珠位置<2^31。
尺取法
1 //尺取法 2 #include<cstdio> 3 #include<iostream> 4 #include<cstring> 5 #include<algorithm> 6 #define N 1000005 7 #define ll long long 8 using namespace std; 9 int n,m,cnt,vis[70],q[N]; 10 struct node{ 11 int p,c; 12 bool operator < (const node &b)const{ 13 return p<b.p; 14 } 15 }t[N]; 16 char gc(){ 17 static char s[1000000],*p1,*p2; 18 if(p1==p2)p2=(p1=s)+fread(s,1,1000000,stdin); 19 if(p1==p2)return EOF; 20 return *p1++; 21 } 22 int read(){ 23 int x=0;char ch=gc(); 24 while(ch>'9'||ch<'0')ch=gc(); 25 while(ch<='9'&&ch>='0')x=x*10+ch-'0',ch=gc(); 26 return x; 27 } 28 29 int main(){ 30 n=read();m=read(); 31 for(int i=1;i<=m;i++){ 32 int x=read(); 33 for(int j=1;j<=x;j++){ 34 int p=read(); 35 t[++cnt]=(node){p,i}; 36 } 37 } 38 sort(t+1,t+1+cnt); 39 int l=1,r=0,num=0; 40 int ans=2147483647; 41 while(r<n){ 42 while(num<m&&r<n){ 43 if(!vis[t[++r].c])num++; 44 vis[t[r].c]++; 45 } 46 if(r>n)break; 47 while(num>=m&&l<=r){ 48 ans=min(ans,t[r].p-t[l].p); 49 ;if(!--vis[t[l++].c])num--; 50 } 51 } 52 printf("%d\n",ans); 53 return 0; 54 }
If you live in the echo,
your heart never beats as loud.
如果你生活在回声里,
你的心跳声永远不会轰鸣作响。