• [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 }
  • 相关阅读:
    spring源码阅读之ioc
    java基础面试题
    【0708】(OOP)编写并输出学员类和教员类
    【0706】综合作业:吃货联盟订餐系统
    【0703作业】输入一批整数,输出其中的最大值和最小值,输入0结束循环
    【0703作业】获取最低价手机价格
    【0703作业】一组成绩降序排列,插入数值
    【0703作业】猜数游戏
    【0702作业】根据数字输出行数(1-9)
    【0702作业】输出1-7对应星期
  • 原文地址:https://www.cnblogs.com/sainsist/p/11379581.html
Copyright © 2020-2023  润新知