bzoj 1293: [SCOI2009]生日礼物
链接: https://www.lydsy.com/JudgeOnline/problem.php?id=1293
思路:用静态链表存一下这些点,然后枚举终点,当前终点枚举k种珠子,分别找到每一种种类在终点之前最近的珠子,保存下距离,维护所有种类珠子离终点的最大值,这就是以当前点为终点的最短场合,最后取所有终点的最短长度就好了。
实现代码:
#include<bits/stdc++.h> using namespace std; const int M = 1e6 + 10; const int inf = 0x3f3f3f3f; int n,m,ans,t; int a[M],nex[M],head[100],b[M]; bool cal(int x){ int tmp = 0; for(int i = 1;i <= m;i ++){ while(a[head[i]] > x){ if(nex[head[i]] == 0) return 0; //这种类的珠子坐标都大于当前终点,不能取得k种直接跳出 head[i] = nex[head[i]]; //更换尾节点,因为是从大到小枚举,之前的尾节点在以后也用不到,直接替换掉就好了 } if(a[head[i]] <= x) tmp = max(tmp,x - a[head[i]]); } ans = min(tmp,ans); return 1; } int main() { int x,cnt = 0; cin>>n>>m; for(int i = 1;i <= m;i ++){ cin>>t; for(int j = 1;j <= t;j ++){ cin>>x; a[++cnt] = x; nex[cnt] = head[i]; head[i] = cnt; b[cnt] = x; } } ans = inf; sort(b+1,b+1+cnt); for(int i = cnt;i >= 1;i --){ if(b[i] != b[i+1]){ if(!cal(b[i])) break; //因为是从大到小的,当前终点无法取得k种,比他小的更不可能,直接跳出就好了 } } cout<<ans<<endl; }