1. 程式人生 > >bzoj1293[SCOI2009]生日禮物 尺取法

bzoj1293[SCOI2009]生日禮物 尺取法

def rip php .com 沒有 數據規模 size space zoj

1293: [SCOI2009]生日禮物

Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 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

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 }

bzoj1293[SCOI2009]生日禮物 尺取法