Stars in the window [segment tree + scan line + discretization + lazy mark]

Stars in the window [segment tree + scan line + discretization + lazy mark]

POJ2482ACwing248

topic:

There are many stars in a sky (think of a plane rectangular coordinate system), and the coordinates and brightness of each star are known (both integers).

Find the maximum total brightness of the stars that can be encircled by a rectangular window of width W and height H (W and H are positive integers). (stars on rectangle borders don't count)

Input format:

The input contains sets of test cases.

The first line of each use case contains 3 integers: n, W, H, representing the number of stars, and the width and height of the rectangular window.

Then there are n lines, each with 33 integers: x, y, c, representing the position (x, y) and brightness of each star.

No two stars are at the same point.

Output format:

Each test case outputs a maximum sum of luminance.

One line for each result.

data range:

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

Input sample:

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

Sample output:

5
6

Code:

#include<bits/stdc++.h>
using namespace std;

#define int long long
const int N = 1e4+5;

int n,W,H,k;
//----------------------------------------
vector<int> v;      //用于y轴离散化
int find_w(int x){
    
      //找到离散化后代表x的数字
    return lower_bound(v.begin(),v.end(),x) - v.begin();
}
//----------------------------------------
struct Edge{
    
    
    int x,y1,y2,c;      //分别表示星星的坐标和亮度
} e[N << 2];            //存储四元组
bool cmp(Edge a,Edge b){
    
    
    if(a.x == b.x)
        return a.c < 0;
    return a.x < b.x;
}                       //按照x排序,方便从左到右扫描
//----------------------------------------
struct T{
    
    
    int l,r;            //区间
    int ans,lazy;        //答案、lazy标记
} tree[N << 3];         //存储线段树

void build(int p,int l,int r){
    
          //建立线段树
    tree[p] = {
    
    l,r,0,0};
    if(l == r)
        return;
    int lc = p<<1,rc = p<<1|1,mid = l+r>>1;
    build(lc,l,mid);
    build(rc,mid + 1,r);
}

void push_down(int p){
    
      //消除lazy标记
    int lc = p<<1,rc = p<<1|1,lazy = tree[p].lazy;
    tree[lc].ans += lazy;
    tree[lc].lazy += lazy;
    tree[rc].ans += lazy;
    tree[rc].lazy += lazy;
    tree[p].lazy = 0;
}

void update(int p,int l,int r,int c){
    
    
    //如果全覆盖的话,可以不着急更新子结点,使用lazy标记做记录
    if(tree[p].l == l && tree[p].r == r){
    
    
        tree[p].lazy += c;
        tree[p].ans += c;
        return;
    }
    push_down(p);   //如果没有全覆盖,则应该线更新子节点后再访问子节点
    int lc = p<<1,rc = p<<1|1,mid = tree[p].l+tree[p].r>>1;
    if(r <= mid)
        update(lc,l,r,c);
    else if(l > mid)
        update(rc,l,r,c);
    else
        update(lc,l,mid,c),update(rc,mid + 1,r,c);
    tree[p].ans = max(tree[lc].ans,tree[rc].ans);       //更新该结点
}

signed main(){
    
    
    int x,y,c;
    while(cin>>n>>W>>H){
    
    
        k = 0;
        v.clear();
        for(int i = 0;i < n;++i){
    
    
            cin>>x>>y>>c;
            e[++k] = {
    
    x,y,y + H - 1,c};
            e[++k] = {
    
    x + W,y,y + H - 1,-c};
            v.push_back(y),v.push_back(y + H - 1);
        }
        sort(v.begin(),v.end());
        v.erase(unique(v.begin(),v.end()),v.end());     //去重离散化

        sort(e + 1,e + k + 1,cmp);              //排序,以便后续扫描

        build(1,0,v.size() - 1);                //建立线段树

        int ans = 0;
        for(int i = 1;i <= k;++i){
    
    
            //扫描到这条边的时候根据c的值考虑是要加入这个星星的亮度还是减去这个星星的亮度
            update(1,find_w(e[i].y1),find_w(e[i].y2),e[i].c);
            //更新ans
            ans =max(ans,tree[1].ans);
        }
        cout<<ans<<"\n";
    }
    return 0;
}

Guess you like

Origin blog.csdn.net/qq_45985728/article/details/123365903