A:Careful Thief
题意:给出n个区间,每个区间的每个位置的权值都是v,然后找长度为k的区间,使得这个区间的所有位置的权值加起来最大,输出最大权值, 所有区间不重叠
思路:贪心的想法,长度为k的区间的起始点肯定是某个区间的起始点,或者长度为k的区间的结束点肯定是某个区间的结束点。
因为存在最优的答案,它的起点不在某个区间的起点,那么只有两种情况。
1° 不属于任何已知区间
2° 在某个已知区间的内部
首先考虑第一种情况 如果不属于任何已知区间,那么根据贪心,我肯定能够往右移使得它是某个区间起点,这样得到的新的答案肯定大于等于原来的答案,因为我移动的这段区间的权值都为0
那么第二种情况,假如现在涵盖的区间横跨两个区间,那么我肯定能够右移结束点使得它与最后的那个区间的结束点对齐,或者左移起始点使得它跟最左边涵盖到的区间的起始点对齐,使得答案更大
然后双指针搞一搞
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 #define ll long long 6 7 #define N 100010 8 9 int t, m, k; 10 11 struct node 12 { 13 int l, r; 14 ll v; 15 ll sum; 16 inline node() {} 17 inline node(int l, int r, int v) : l(l), r(r), v(v) {} 18 19 inline void scan() 20 { 21 scanf("%d%d%lld", &l, &r, &v); 22 sum = (ll)(r - l + 1) * v; 23 } 24 25 inline bool operator < (const node& b) const 26 { 27 return l < b.l; 28 } 29 }arr[N]; 30 31 int main() 32 { 33 scanf("%d", &t); 34 while (t--) 35 { 36 scanf("%d%d", &m, &k); 37 for (int i = 1; i <= m; ++i) 38 arr[i].scan(); 39 40 sort(arr + 1, arr + m + 1); 41 int L, R; 42 int j = 1; 43 ll ans = 0; 44 ll tmp = 0; 45 for (int i = 1; i <= m; ++i) 46 { 47 L = arr[i].l; 48 R = L + k - 1; 49 while (arr[j].r <= R && j <= m) 50 { 51 tmp += arr[j].sum; 52 ++j; 53 } 54 ll res = 0; 55 if(j <= m) 56 { 57 res = arr[j].v * max(0, R - arr[j].l + 1); 58 } 59 tmp += res; 60 ans = max(ans, tmp); 61 tmp -= res; 62 tmp -= arr[i].sum; 63 } 64 tmp = 0; 65 j = m; 66 for(int i = m; i >= 1; --i) 67 { 68 R = arr[i].r; 69 L = R - k + 1; 70 while(arr[j].l >= L && j >= 1) 71 { 72 tmp += arr[j].sum; 73 --j; 74 } 75 ll res = 0; 76 if(j >= 1) 77 { 78 res = arr[j].v * max(0, arr[j].r - L + 1); 79 } 80 tmp += res; 81 ans = max(ans, tmp); 82 tmp -= res; 83 tmp -= arr[i].sum; 84 } 85 printf("%lld\n",ans); 86 } 87 return 0; 88 }