[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 }

 

posted @ 2019-08-19 20:49  祈梦生  阅读(224)  评论(0编辑  收藏  举报