ACWing 248. 窗内的星星|扫描线+懒惰标记

传送门

题目描述

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

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

输入格式

输入包含多组测试用例。

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

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

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

输出格式

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

每个结果占一行。

数据范围

1≤n≤10000,
1≤W,H≤1000000,
10≤x,y<231

输入样例:

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

题解:https://www.cnblogs.com/l999q/p/11366840.html可参考这篇博客,不同点在于它是维护亮度和(相当于维护那篇博客中的最大cnt值)。

要注意的是:

  1. 题目中说矩形边界上的星星不算,那么我们线段的上边界要减一(存边界的四元组的时候处理)。
  2. 若一个矩形的右边界与另一个矩形的左边界重合时,先减去左边矩阵的亮度再加上右边矩阵的亮度。

代码:

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 2e4 + 10;
struct node{
    int x,y1,y2,val;
    node() {}
    node(int x, int y1, int y2,int val){
        this->x = x; this->val = val;
        this->y1 = y1; this->y2 = y2;
    }
    bool operator <(const node &t)const {
        return x<t.x;
    }
};
struct Tree{
    int l,r;
    int val,lazy;
}t[N<<2];
vector<node> a;
vector<int> v;
void build(int rt,int l,int r) {
    t[rt].l = l,t[rt].r = r;
    t[rt].val = 0; t[rt].lazy = 0;
    if (l == r) return;
    int mid = (l+r)>>1;
    build(rt<<1,l,mid);
    build(rt<<1|1,mid+1,r);
}
void update(int rt,int l,int r,int val) {
    if (l <= t[rt].l && r >= t[rt].r) {
        t[rt].val += val;
        t[rt].lazy += val;
        return;
    }
    if (t[rt].lazy) {
        t[rt<<1].val += t[rt].lazy;
        t[rt<<1].lazy += t[rt].lazy;
        t[rt<<1|1].val += t[rt].lazy;
        t[rt<<1|1].lazy += t[rt].lazy;
        t[rt].lazy = 0;
    }
    int mid = (t[rt].l+t[rt].r)>>1;
    if (l <= mid) update(rt<<1,l,r,val);
    if (r > mid) update(rt<<1|1,l,r,val);
    t[rt].val = max(t[rt<<1].val,t[rt<<1|1].val);
}
int main() {
    int n,w,h;
    while (~scanf("%d%d%d",&n,&w,&h) ) {
        v.clear();a.clear();
        for(int i = 0; i < n; i++) {
            int x,y,c;
            scanf("%d%d%d",&x,&y,&c);
            v.push_back(y);
            v.push_back(y+h-1);
            a.push_back(node(x,y,y+h-1,c));
            a.push_back(node(x+w,y,y+h-1,-c)); // y坐标边界要减,x坐标不要减
        }
        v.push_back(-1);
        sort(a.begin(),a.end());
        sort(v.begin(),v.end());
        v.erase(unique(v.begin(),v.end()),v.end());
        n=v.size();
        build(1,0,n);
        int ans = 0;
        for (int i = 0; i < n; i++) {
            int l = lower_bound(v.begin(),v.end(),a[i].y1) - v.begin();
            int r = lower_bound(v.begin(),v.end(),a[i].y2) - v.begin();
            update(1,l,r,a[i].val);
            if (a[i].val>0) ans = max(ans,t[1].val);
        }
        printf("%lld
",ans);
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/l999q/p/11366867.html