妈个鸡,要不是队友提醒,我能把题面上的那封情书读完,读了一半多了都
然后题意就是,在一个平面直角坐标系上,有一些点,每个点有一个权值,用一个矩形框去框住他们,问怎么才能使框住的所有点的权值和最大,边界上的点不算。
边界上的点 不算,我之前只做到过一次边界上的点算的啊,怎么办,把长和宽都各自-1就好啦。处理之后,设长为w,宽为h。
大概就是,把一个点沿一个方向,假如说是x轴,沿x轴向正方向延长w个长度,然后这是一条入边,在y+h+1上,建一条相应的出边,就是权值取个负数,就相当于把这条边又给删去啦。
然后将所有的边按y排序,根据y从小到大,加入边,就是更新(x,x+w)这个区间。想想,这样的话,某一点 x0就可以有x0为右边界的矩形的框住的权值和,然后y又是从下往上扫的,而且还有出边,所以(x0,y0)表示以这个点为右上角的矩形框住的权值和。
比如我们更新到了y=yi,在把所有y=yi的边都更新之后,线段树存的是x,对应的最大值。所以线段树的根的最大值,就代表在y=yi下(xi,yi)为右上角的矩形框住最大权值和。
然后y从0扫到最大值,就可以得到最大权值和啦。
代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> using namespace std; #define maxn 10002 #define uint unsigned int uint x_data[maxn * 2], y_data[maxn * 2]; struct Node { unsigned int x, y; int val; void made(unsigned int a, unsigned int b,int c) { x = a, y = b, val = c; } }node[maxn]; struct edge_mode { int y, l, r, val; void edge_make(int y, int l, int r, int val) { this->y = y; this->l = l; this->r = r; this->val = val; } }edge[20005]; struct segment { int add, max; }segtree[160005]; bool cmp(edge_mode a, edge_mode b) { if (a.y < b.y) return true; else return false; } void init(int id, int l, int r) { segtree[id].add = segtree[id].max = 0; if (l == r) return; init(id << 1, l, (l + r) >> 1); init(id << 1 | 1, ((l + r) >> 1) + 1, r); } void update(int id, int l, int r, int nl, int nr, int val) { if (r<nl || l>nr) return; if (l >= nl&&r <= nr) { segtree[id].add += val; segtree[id].max += val; return; } update(id << 1, l, (l + r) >> 1, nl, nr, val); update(id << 1 | 1, ((l + r) >> 1) + 1, r, nl, nr, val); segtree[id].max = max(segtree[id << 1].max, segtree[id << 1 | 1].max) + segtree[id].add; } int main() { //freopen("input.txt", "r", stdin); int n, w, h; while ((scanf("%d%d%d", &n, &w, &h)) == 3) { --w, --h; init(1, 0, 20000); //unsigned int x, y; for (int i = 0; i < n; ++i) { scanf("%u%u%d", &node[i].x, &node[i].y, &node[i].val); x_data[2 * i] = node[i].x, x_data[2 * i + 1] = node[i].x + w; y_data[2 * i] = node[i].y, y_data[2 * i + 1] = node[i].y + h + 1; } sort(x_data, x_data + 2 * n); sort(y_data, y_data + 2 * n); uint x_d = unique(x_data, x_data + 2 * n) - x_data, y_d = unique(y_data, y_data + 2 * n) - y_data; for (int i = 0; i < n; ++i) { int x1 = lower_bound(x_data, x_data + x_d, node[i].x) - x_data; int y1 = lower_bound(y_data, y_data + y_d, node[i].y) - y_data; int x2 = lower_bound(x_data, x_data + x_d, node[i].x + w) - x_data; int y2 = lower_bound(y_data, y_data + y_d, node[i].y + h + 1) - y_data; edge[2 * i].edge_make(y1, x1, x2, node[i].val); edge[2 * i + 1].edge_make(y2, x1, x2, -1 * node[i].val); //printf("%d %d %d %d %d\n", x1, y1, x2, y2, node[i].val); } sort(edge, edge + 2 * n, cmp); int ans = 0; for (int i = 0, t = 0; i <= 20000; i++) { while (edge[t].y == i&&t < 2 * n) { update(1, 0, 20000, edge[t].l, edge[t].r, edge[t].val); t++; } //if (i <= 5) //printf("%d\n", segtree[1].max); ans = max(ans, segtree[1].max); } printf("%d\n", ans); } //while (1); return 0; }