首页 > 其他分享 >AcWing 248. 窗内的星星

AcWing 248. 窗内的星星

时间:2022-12-19 17:14:57浏览次数:62  
标签:星星 窗内 include 亮度 seg ys 矩形 248 AcWing

\(AcWing\) \(248\). 窗内的星星

良心题解

一、题目描述

在一个天空中有很多星星(看作平面直角坐标系),已知每颗星星的坐标和亮度(都是整数)。

求用宽为 \(W\)、高为 \(H\) 的矩形窗口(\(W,H\) 为正整数) 能圈住的星星的亮度总和最大是多少。(矩形边界上的星星不算)

输入格式
输入包含多组测试用例。

每个用例的第一行包含 \(3\) 个整数:\(n,W,H\),表示星星的数量,矩形窗口的宽和高。

然后是 \(n\) 行,每行有 \(3\) 个整数:\(x,y,c,\) 表示每个星星的位置 \((x,y)\) 和亮度。

没有两颗星星在同一点上。

输出格式
每个测试用例输出一个亮度总和最大值。

每个结果占一行。

数据范围
\(1≤n≤10000,\\ 1≤W,H≤1000000,\\ 0≤x,y<2^{31}\)

输入样例:

3 5 4
1 2 3
2 3 2
6 3 1

3 5 4
1 2 3
2 3 2
5 3 1

输出样例:

5
6

二、解题思路

矩形只有中心在一定的范围才能括住特定的星星,假设只有两个星星,括住这两个星星的矩形范围的重叠部分,就是矩形的最佳位置,即能括住最多的亮度的星星

每个星星都有一个矩形,以星星为矩形的左下角(实际上,星星应该在矩形的中心,但坐标平移即可,不影响结果)

把每个矩形的左右两个边, 按照\(x\)升序排列,当\(x\)相同时,星星亮度小的优先

\(Q\):为什么相同\(x\)坐标的边要按照星星亮度再排序一次?
因为题目要求的不包含边界,则达到一个新\(x\)坐标时,应该 把负权减掉

\(c\)为星星的亮度,矩形左边赋值\(c\), 右边赋值\(-c\),枚举每个横坐标,线段树中维护着最大的亮度,即是答案

注意这题需要知道最大值的大小,所以 需要懒标记,亚特兰蒂斯那题只需要知道大于\(0\)即可,分析可得不需要懒标记

本例注意和 亚特兰蒂斯 那道题目对比

三、问题集

请问一下 样例中第二个答案是\(6\)也就是三个星星都能框进去 而数据是这样的:

3 5 4
1 2 3
2 3 2
5 3 1

最左边的点是(\(1,2\))最右边的点是(\(5,3\))
那么想要把这两个同时框进去不是需要至少宽度是\(6\)嘛也就是从\(0\)框到\(6\)
可样例中宽度是\(5\) 那么应该会有一个点卡在边界上那么不就不能算是有贡献了嘛?

\(yxc\)回复:
从\(0.5\)到\(5.5\)的框就可以啦,所以宽度是\(5\)的话可以同时包含\((1, 2)\)和\((5, 3)\)
它只是要求星星在整点上,但是我框的矩形顶点是不用在整点上的,所以我们可以平移\(0.5\)这样就能多框一段了。

四、实现代码

#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <vector>

using namespace std;
typedef long long LL;
const int N = 10010;

struct Seg {
    LL x, y1, y2, k;
    bool operator<(const Seg &l) const {
        return x < l.x || x == l.x && k > l.k;
    }
} seg[N << 1];

struct Node {
    int l, r;
    LL maxc, lazy;
} tr[N << 3];

int n, w, h;
vector<LL> ys;

void pushup(int u) {
    tr[u].maxc = max(tr[u << 1].maxc, tr[u << 1 | 1].maxc);
}

void build(int u, int l, int r) {
    tr[u] = {l, r};
    if (l == r) return;
    int mid = l + r >> 1;
    build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
}

void pushdown(int u) {
    if (tr[u].lazy) {
        tr[u << 1].maxc += tr[u].lazy;
        tr[u << 1].lazy += tr[u].lazy;
        tr[u << 1 | 1].maxc += tr[u].lazy;
        tr[u << 1 | 1].lazy += tr[u].lazy;
        tr[u].lazy = 0;
    }
}

void modify(int u, int l, int r, int k) {
    if (l <= tr[u].l && tr[u].r <= r) {
        tr[u].lazy += k;
        tr[u].maxc += k;
        return;
    }

    pushdown(u);
    int mid = tr[u].l + tr[u].r >> 1;
    if (l <= mid) modify(u << 1, l, r, k);
    if (r > mid) modify(u << 1 | 1, l, r, k);

    pushup(u);
}

int find(LL x) {
    return lower_bound(ys.begin(), ys.end(), x) - ys.begin();
}

int main() {
    //加快读入
    ios::sync_with_stdio(false), cin.tie(0);

    while (cin >> n >> w >> h) {
        ys.clear();
        for (int i = 1; i <= n; i++) {
            LL x, y, c;
            cin >> x >> y >> c;
            seg[2 * i - 1] = {x, y, y + h - 1, c};
            seg[2 * i] = {x + w - 1, y, y + h - 1, -c};
            ys.push_back(y), ys.push_back(y + h - 1);
        }

        sort(ys.begin(), ys.end());
        ys.erase(unique(ys.begin(), ys.end()), ys.end());

        sort(seg + 1, seg + 1 + 2 * n);

        build(1, 0, ys.size() - 1);

        LL res = 0;
        for (int i = 1; i <= 2 * n; i++) {
            modify(1, find(seg[i].y1), find(seg[i].y2), seg[i].k);
            res = max(res, tr[1].maxc);
        }
        printf("%d\n", res);
    }
    return 0;
}

标签:星星,窗内,include,亮度,seg,ys,矩形,248,AcWing
From: https://www.cnblogs.com/littlehb/p/16992576.html

相关文章

  • Acwing 第82场周赛ABC
    https://www.acwing.com/activity/content/competition/problem_list/2696/C我前几个月碰到了原题hh,原题在cf上4782.第k个数题目大意:输出从大到小的第k个数字输入......
  • AcWing 2280. 最优标号
    AcWing2280.最优标号很神奇的建图,但是确实很有道理//多个进行匹配的问题#include<bits/stdc++.h>usingnamespacestd;usingll=longlong;constintN=1005,M=1e......
  • 【LeeCode】2488. 统计中位数为 K 的子数组 -- 太难了
    【题目描述】给你一个长度为n的数组nums,该数组由从1到n的不同整数组成。另给你一个正整数k。统计并返回num中的中位数等于k的非空子数组的数目。注意:数组......
  • Acwing 第 78 场周赛 ABC
    明天考完就可以放假咯,水一篇博客练练手https://www.acwing.com/activity/content/2622/4719.商品种类题目大意:货架中摆放着n件商品,每件商品都有两个属性:名称和产地......
  • acwing 2237. 猪
    2237.猪分层图的简化,思路tql,大大的减少了点的基数如果这个猪房已经被用过了,那就直接从用过的那个人哪里流过来就可以了如果这个猪房没有用过,那就从超级起点流出来。这......
  • LeetCode 题解 2487. 从链表中移除节点
    2487.从链表中移除节点-力扣(Leetcode)题解思路一:递归逆序structListNode*removeNodes(structListNode*head){if(head->next==NULL)//遍历到链表末尾......
  • AcWing 261. 旅馆 【线段树】
    [NOIP2015普及组]推销员题目背景NOIP2015普及组T4题目描述阿明是一名推销员,他奉命到螺丝街推销他们公司的产品。螺丝街是一条死胡同,出口与入口是同一个,街道的一侧......
  • AcWing 205. 斐波那契
    \(AcWing\)\(205\).斐波那契​​题目传送门​​一、题目描述在斐波那契数列中,\(F_ib_0=0,F_ib_1=1,F_ib_n=F_ib_{n−1}+F_ib_{n−2}(n>1)\)。给定整数\(n\),求\(F_ib_n~......
  • P1248 加工生产调度&P2123 皇后游戏
    P1248加工生产调度P2123皇后游戏Johnson法则早就该会了……一般地,设\(c_i\)表示完成第\(i\)个后的时间,得\[c_i=\begin{cases}a_1+b_1&(i=1)\\\max\left(c_......
  • AcWing2437. Splay 题解
    题目大意:splay执行区间翻转示例程序:#include<bits/stdc++.h>usingnamespacestd;constintmaxn=1e5+5;intn,m;structNode{ints[2],p,v;intsz,flag......