考虑poj3320尺取法的做法,与此题基本一样,但是此题的 位置 的范围到2^31 尺取法不可。
将每种珠子所在的位置排序。
每种珠子要维护一个指针,指到已经用到这个种类的哪个珠子。
所以尺取法用堆优化,每次从堆中取出最小的,相当于尺取法的头指针向后移动。
然后从每种珠子里向后取出一个位置(指针++)(已经排过序,是单调递增的),加进堆。
再从每种其他的珠子里 把 在 新加入的珠子位置之前的 位置全都加进堆。
更新答案。
直到某种类珠子已经全用完。
由于每个位置可能有很多珠子,插入堆时要用一个二元组。
1 #include<cstdio> 2 #include<vector> 3 #include<algorithm> 4 #include<queue> 5 using namespace std; 6 struct Point 7 { 8 int x,y; 9 Point(const int &a,const int &b) 10 { 11 x=a; 12 y=b; 13 } 14 Point(){} 15 }; 16 bool operator < (const Point &a,const Point &b){return a.x!=b.x ? a.x<b.x : a.y<b.y;} 17 bool operator > (const Point &a,const Point &b){return a.x!=b.x ? a.x>b.x : a.y>b.y;} 18 priority_queue<Point,vector<Point>,greater<Point> >Heap; 19 vector<int>a[61]; 20 vector<int>::iterator p[61]; 21 int n,m,k,t,maxv,time[61],ans=2147483647; 22 Point topv; 23 int main() 24 { 25 scanf("%d%d",&n,&m); 26 for(int i=1;i<=m;i++) 27 { 28 scanf("%d",&k); 29 for(int j=1;j<=k;j++) 30 { 31 scanf("%d",&t); 32 a[i].push_back(t); 33 } 34 sort(a[i].begin(),a[i].end()); 35 p[i]=a[i].begin(); 36 } 37 for(int i=1;i<=m;i++) 38 { 39 maxv=max(maxv,*a[i].begin()); 40 Heap.push( Point( *a[i].begin() , i ) ); 41 p[i]++; 42 time[i]++; 43 } 44 for(int i=1;i<=m;i++) 45 for(;p[i]!=a[i].end()&&((*p[i])<=maxv);p[i]++) 46 { 47 time[i]++; 48 Heap.push( Point( *p[i] , i ) ); 49 } 50 while(1) 51 { 52 topv=Heap.top(); 53 int headv=topv.y; 54 ans=min(ans,maxv-topv.x); 55 Heap.pop(); 56 time[headv]--; 57 if(!time[headv]) 58 { 59 if(p[headv]==a[headv].end()) 60 break; 61 Heap.push( Point( *p[headv] , headv ) ); 62 maxv=*p[headv]; 63 time[headv]++; 64 for(int i=1;i<=m;i++) 65 for(;p[i]!=a[i].end()&&((*p[i])<=maxv);p[i]++) 66 { 67 time[i]++; 68 Heap.push( Point( *p[i] , i ) ); 69 } 70 } 71 } 72 printf("%d ",ans); 73 return 0; 74 }