题解 P1502 【窗口的星星】

· · 题解

这是一道离散化加线段树

我们把每个星星都看成属于它那个矩形的左下角

再按照x轴和y轴离散化

把y轴用线段树处理,x轴扫过去

扫到一个矩形就加相应的light值,相反扫出矩形就减去相应的light值(线段树操作)

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

typedef long long ll;
const int MAX = 100010;

int n, w, h, t;
struct Node {
    int light, x_1, x_2, y_1, y_2;
}s[MAX];
struct node {
    int xx, yy, id;
}L[MAX << 2];
int tot;
struct nOde {
    int lazy, sum;
}tree[MAX << 2];
int f[MAX][101], g[MAX][101];

inline int read() {
    int s = 0, w = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9') {
        if(ch == '-') w = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9') {
        s = s * 10 + ch - '0';
        ch = getchar();
    }
    return s * w;
}

bool cmp_x(node a, node b) {return a.xx < b.xx;}
bool cmp_y(node a, node b) {return a.yy < b.yy;}
bool cmp_X(Node a, Node b) {return a.x_1 == b.x_1 ? a.x_2 < b.x_2 : a.x_1 < b.x_1;}
void push_down(int u) {
    if(tree[u].lazy) {
        tree[u << 1].lazy += tree[u].lazy;
        tree[u << 1 | 1].lazy += tree[u].lazy;
        tree[u << 1].sum += tree[u].lazy;
        tree[u << 1 | 1].sum += tree[u].lazy;
        tree[u].lazy = 0;
    }
}
void change_1(int u, int x, int y, int a, int b, int k) {
    if(a <= x && b >= y) {
        tree[u].lazy += k;
        tree[u].sum += k;
        push_down(u);
        return ;
    }
    int mid = (x + y) >> 1;
    push_down(u);
    if(a <= mid) change_1(u << 1, x, mid, a, b, k);
    if(b > mid) change_1(u << 1 | 1, mid + 1, y, a, b, k);
    tree[u].sum = max(tree[u << 1].sum, tree[u << 1 | 1].sum);
}
int ask(int u, int x, int y) {
    if(x == y) return tree[u].sum;
    int mid = (x + y) >> 1;
    push_down(u);
    return max(ask(u << 1, x, mid), ask(u << 1 | 1, mid + 1, y));
    return 0;
}
int main()
{
    t = read();
    while(t--) {
        tot = 0;
        n = read(), w = read(), h = read();
        for(int i = 1; i <= n; i++) {
            int x = read(), y = read();
            s[i].x_1 = s[i].x_2 = s[i].y_1 = s[i].y_2 = 0;
            s[i].light = read();

            L[++tot].xx = x;
            L[tot].yy = y;
            L[tot].id = i;

            L[++tot].xx = x + w - 1;
            L[tot].yy = y - h + 1;
            L[tot].id = i;
        }
        sort(L + 1, L + 1 + tot, cmp_y);//离散化x,y轴
        int ty = 0;
        for(int i = 1; i <= tot; i++) {
            if(L[i].yy != L[i - 1].yy) ty++;
            if(!s[L[i].id].y_1) s[L[i].id].y_1 = ty;
            else s[L[i].id].y_2 = ty; 
        }
        sort(L + 1, L + 1 + tot, cmp_x);
        int tx = 0;
        for(int i = 1; i <= tot; i++) {
            if(L[i].xx != L[i - 1].xx) tx++;
            if(!s[L[i].id].x_2) s[L[i].id].x_2 = tx, f[tx][++f[tx][0]] = L[i].id;
            else s[L[i].id].x_1 = tx, g[tx][++g[tx][0]] = L[i].id;
        }
        //for(int i = 1; i <= n; i++) {printf("\nx_1: %d  x_2: %d  y_1: %d  y_2: %d  light: %d\n",  s[i].x_1, s[i].x_2, s[i].y_1, s[i].y_2, s[i].light);}
        //sort(s + 1, s + n + 1, cmp_X);
        int ans = 0;
        for(int i = 1; i <= tx; i++) {
            for(int j = 1; j <= f[i][0]; j++) {
                int v = f[i][j];
                change_1(1, 1, ty, s[v].y_1, s[v].y_2, s[v].light);
            }
            ans = max(ans, /*ask(1, 1, ty)*/tree[1].sum);
            for(int j = 1; j <= g[i][0]; j++) {
                int v = g[i][j];
                change_1(1, 1, ty, s[v].y_1, s[v].y_2, -s[v].light);
            }
        }
        printf("%d\n", ans);
        for(int i = 1; i <= tx; i++) f[i][0] = g[i][0] = 0;
    }
    return 0;
}