思路:
考虑到补签卡一定是连续放置才更优,所以直接根据起始位置枚举。预先处理区间之间的gap的前缀和,在枚举过程中二分即可。复杂度O(nlog(n))。
实现:
1 #include <iostream> 2 #include <cstdio> 3 #include <vector> 4 #include <algorithm> 5 using namespace std; 6 typedef long long ll; 7 8 const ll INF = 0x3f3f3f3f; 9 10 int main() 11 { 12 int n, m; 13 while (scanf("%d %d", &n, &m) != EOF) 14 { 15 vector<pair<int, int>> v; 16 int x, y; 17 for (int i = 0; i < n; i++) 18 { 19 scanf("%d %d", &x, &y); 20 v.push_back(pair<int, int>(x, y)); 21 } 22 sort(v.begin(), v.end()); 23 vector<pair<int, int>> res; 24 res.push_back(v[0]); 25 for (int i = 1; i < v.size(); i++) 26 { 27 if (v[i].first > res.back().second + 1) res.push_back(v[i]); 28 else res.back().second = max(res.back().second, v[i].second); 29 } 30 vector<ll> sum(res.size() - 1); 31 for (int i = 0; i < res.size() - 1; i++) 32 sum[i] = (ll)res[i + 1].first - 1 - res[i].second; 33 sum.push_back(INF); 34 for (int i = 1; i < sum.size(); i++) 35 sum[i] += sum[i - 1]; 36 ll maxn = 0; 37 for (int i = 0; i < sum.size(); i++) 38 { 39 ll tmp = (i == 0 ? 0 : sum[i - 1]); 40 int pos = upper_bound(sum.begin() + i, sum.end(), m + tmp) - sum.begin(); 41 ll tmp2 = (pos == i ? m : m - (sum[pos - 1] - tmp)); 42 maxn = max(maxn, res[pos].second - res[i].first + 1 + tmp2); 43 } 44 printf("%lld ", maxn); 45 } 46 return 0; 47 }