把所有人按照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 }