把所有人按照sing从大到小排序,然后枚举sing值最高的人i,比他高的必须得去talk,维护必须去talk的这波人的最大值,作为maxn。
然后两个情况,如果maxn>=sing[i],那么i作为sing最高的人情况下,显然talk中的最大值不可能小于maxn,我们再怎么往talk组加人,也只可能会让差距变大,所以把maxn - sing[i]和答案取min。
如果maxn < sing[i],我们就去找i+1到n,这些人中,talk最接近sing[i]的两个人,一个大于等于sing[i],一个小于等于sing[i],用set中lower_bound实现,对于小于情况加入负数即可。注意这两个人必须都得大于maxn,才有意义。然后继续取min。
maxn初值必须得是负无穷,要不然,第一个人的sing可能跟初值为0的maxn取出一个不存在的情况。被这个边界卡了一下午....
1 #include <cstdio> 2 #include <set> 3 #include <algorithm> 4 using namespace std; 5 typedef long long ll; 6 struct peo 7 { 8 ll sing,talk; 9 friend bool operator < (peo a,peo b) 10 { 11 return a.sing > b.sing; 12 } 13 }; 14 multiset <ll> st[2]; 15 ll maxn,res; 16 int T,n; 17 peo vec[100100]; 18 int main() 19 { 20 for (scanf("%d",&T);T != 0;T--) 21 { 22 st[0].clear(); 23 st[1].clear(); 24 maxn = -10000000000; 25 res = 1000000000000000000; 26 scanf("%d",&n); 27 for (int i = 1;i <= n;i++) 28 scanf("%lld%lld",&vec[i].sing,&vec[i].talk); 29 sort(vec + 1,vec + n + 1); 30 for (int i = 1;i <= n;i++) 31 { 32 st[0].insert(-vec[i].talk); 33 st[1].insert(vec[i].talk); 34 } 35 for (int i = 1;i <= n;i++) 36 { 37 st[0].erase(st[0].find(-vec[i].talk)); 38 st[1].erase(st[1].find(vec[i].talk)); 39 if (vec[i].sing <= maxn) 40 { 41 res = min(maxn - vec[i].sing,res); 42 }else 43 { 44 res = min(vec[i].sing - maxn,res); 45 if (st[0].lower_bound(-vec[i].sing) != st[0].end()) 46 { 47 if (-*st[0].lower_bound(-vec[i].sing) >= maxn) 48 res = min(vec[i].sing + *st[0].lower_bound(-vec[i].sing),res); 49 } 50 if (st[1].lower_bound(vec[i].sing) != st[1].end()) 51 { 52 res = min(*st[1].lower_bound(vec[i].sing) - vec[i].sing,res); 53 } 54 } 55 maxn = max(vec[i].talk,maxn); 56 } 57 printf("%lld\n",res); 58 } 59 return 0; 60 }