zoukankan      html  css  js  c++  java
  • [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
    ", ans);
    85     }
    86 }
  • 相关阅读:
    java_oop_方法2
    POJ 3276 Face The Right Way(反转)
    POJ 3276 Face The Right Way(反转)
    POJ 2566 Bound Found(尺取法,前缀和)
    POJ 2566 Bound Found(尺取法,前缀和)
    POJ 3320 Jessica's Reading Problem(尺取法)
    POJ 3320 Jessica's Reading Problem(尺取法)
    POJ 3061 Subsequence(尺取法)
    POJ 3061 Subsequence(尺取法)
    HDU 1222 Wolf and Rabbit(欧几里得)
  • 原文地址:https://www.cnblogs.com/sainsist/p/11379581.html
Copyright © 2011-2022 走看看