[2019杭电多校第六场][hdu6638]Snowy Smile(维护区间最大子段和)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6638
题意为在一个平面上任意选择一个长方形,使得长方形内点权和最大。
因为长方形可以任意选择,所以上下边一定在某些点上。所以可以枚举上下边。
将上下边看成一条直线y,上下边之间的点看成直线y上的点,则题意就转化成求直线y上最大子段和(子段和的左右边界即是长方形的左右边)。
用线段树维护(区间和&最大前缀和&最大后缀和)就可以维护得到区间最大子段和。
显然需要离散化(雾
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<string> 5 #include<algorithm> 6 #define lson l, mid, i << 1 7 #define rson mid + 1, r, i << 1 | 1 8 using namespace std; 9 typedef long long ll; 10 const int maxn = 5000 + 10; 11 struct node { 12 ll sum, max_sum, max_q, max_h;//区间和,区间最大子段和,最大前缀和,最大后缀和。 13 }T[maxn * 4]; 14 struct P { 15 int x, y; 16 ll w; 17 }p[maxn]; 18 int x[maxn], y[maxn]; 19 bool cmp(P a, P b) { 20 if (a.y == b.y) 21 return a.x < b.x; 22 return a.y < b.y; 23 } 24 void up(int i) { 25 T[i].sum = T[i << 1].sum + T[i << 1 | 1].sum; 26 T[i].max_sum = max(T[i << 1 | 1].max_q + T[i << 1].max_h, max(T[i << 1].max_sum, T[i << 1 | 1].max_sum)); 27 T[i].max_q = max(T[i << 1].max_q, T[i << 1].sum + T[i << 1 | 1].max_q); 28 T[i].max_h = max(T[i << 1 | 1].max_h, T[i << 1].max_h + T[i << 1 | 1].sum); 29 } 30 void build(int l, int r, int i) { 31 T[i].sum = T[i].max_sum = T[i].max_q = T[i].max_h = 0; 32 if (l == r) 33 return; 34 int mid = l + r >> 1; 35 build(lson); 36 build(rson); 37 } 38 void update(int pos, int w, int l, int r, int i) { 39 if (l == r) { 40 T[i].sum += w; 41 T[i].max_sum = T[i].max_q = T[i].max_h = T[i].sum; 42 return; 43 } 44 int mid = l + r >> 1; 45 if (pos <= mid) 46 update(pos, w, lson); 47 else 48 update(pos, w, rson); 49 up(i); 50 } 51 ll f[maxn]; 52 int main() { 53 int t; 54 scanf("%d", &t); 55 while (t--) { 56 int n; 57 ll ans = 0; 58 scanf("%d", &n); 59 for (int i = 1; i <= n; i++) { 60 scanf("%d%d%lld", &p[i].x, &p[i].y, &p[i].w); 61 x[i] = p[i].x, y[i] = p[i].y; 62 } 63 sort(x + 1, x + 1 + n); 64 sort(y + 1, y + 1 + n); 65 int xx = unique(x + 1, x + 1 + n) - x - 1, yy = unique(y + 1, y + 1 + n) - y - 1; 66 for (int i = 1; i <= n; i++) { 67 p[i].x = lower_bound(x + 1, x + 1 + xx, p[i].x) - x; 68 p[i].y = lower_bound(y + 1, y + 1 + yy, p[i].y) - y; 69 } 70 sort(p + 1, p + 1 + n, cmp); 71 int now = 1; 72 for (int i = 1; i <= yy; i++) { 73 build(1, xx, 1); 74 for (int j = i, k = now; j <= yy; j++) { 75 while (k <= n && p[k].y == j) { 76 update(p[k].x, p[k].w, 1, xx, 1); 77 k++; 78 } 79 if (j == i) 80 now = k; 81 ans = max(ans, T[1].max_sum); 82 } 83 } 84 printf("%lld\n", ans); 85 } 86 }