1. 程式人生 > >BZOJ 1293: [SCOI2009]生日禮物 貪心

BZOJ 1293: [SCOI2009]生日禮物 貪心

blog 應該 desc pri () lac class lap ems

1293: [SCOI2009]生日禮物

Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 2513 Solved: 1370
[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。

題意:在數軸上求一個最短區間包含k種顏色的點。 算法:貪心; 枚舉選擇區間有點像隊列的操作。 讀入的時候先用一個now數組記錄第i種顏色被選到的點的在數軸上位置,用一個places數組記錄下標。(由於是按升序讀入,所以不用多一步sort) 初始狀態即為每種顏色的第一個點的最大最小值的差,樣例為max(5,1,1)-min(5,1,1)。 所以我們往後枚舉區間的時候就貪心地把當前區間最左邊的點覆蓋同種顏色的下一個點,然後最左邊的點指針右移到下個點(如果最左邊的點有多個,則選擇它同種顏色的點最近的一個) 重復此操作,找出最大最小值並更新答案,操作次數固定為n-k+1.所以時間效率應該是O((n-k+1)*k)? 由於T[i]沒給範圍,所以二維數組開到最大會MLE。 代碼: 技術分享
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 #define inf 0x7f7f7f7f;
 6 using namespace std;
 7 int n,m;
 8 int i,j;
 9 int l,hh;
10 long long ans,maxn,minn;
11 long long now[61],places[61];
12 int counts[61],num[61];
13 int a[61
][100001]; 14 int main() 15 { 16 scanf("%d%d",&n,&m); 17 for (i=1;i<=m;i++) { 18 scanf("%d",&num[i]); 19 for (j=1;j<=num[i];j++) { 20 scanf("%d",&a[i][j]); 21 if (j==1) { 22 now[i]=a[i][j];//記錄位置 23 places[i]=j;//記錄下標 24 } 25 } 26 } 27 ans=inf; 28 while (hh!=n-m+1) { 29 maxn=-inf; minn=inf; l=0;hh++; 30 for (i=1;i<=m;i++) { 31 if (now[i]>maxn) maxn=now[i]; 32 if (now[i]<minn) { 33 minn=now[i]; l=i; 34 } 35 if (now[i]==minn) { 36 if (a[i][places[i]+1]<=a[l][places[l]+1]){ 37 minn=now[i]; 38 l=i; 39 } 40 } 41 } 42 //printf("%d %d\n",maxn,minn); 43 if (places[l]!=num[l]) { 44 now[l]=a[l][places[l]+1]; 45 places[l]++; 46 //pos=places[i]; 47 }//貪心移動區間 48 if (maxn-minn<ans) ans=maxn-minn; //更新答案 49 50 } 51 printf("%lld",ans); 52 } 53
View Code

BZOJ 1293: [SCOI2009]生日禮物 貪心