题目链接:https://vjudge.net/problem/HDU-6638
题意:n个点,画一个矩形,使得矩形内的所有点的权值最大,求最大权值
题解:首先将坐标离散化到 O(n) 的范围内,方便后续的处理。 将所有点按照y坐标排序,枚举矩形的上边界,然后往后依次加入每行的点,这样就确定了 矩形的上下边界。线段树维护下每个点的权值,则答案即为最大连续子段和,。 时间复杂度 O(n 2 log n)。维护的时候还要记录左连续,右连续,区间和,区间连续最大值,方便在pushup的时候使用。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2010;
struct Point {
int x, y, w;
bool operator < (const Point &b) const {
if(y != b.y) return y < b.y;
else return x < b.x;
}
}p[N];
int n, b[N], len1, len2;
struct node {
int l, r;
ll maxx, lm, rm, sum;
}tree[N << 2];
void build(int l, int r, int cur) {
tree[cur].l = l;
tree[cur].r = r;
tree[cur].maxx = tree[cur].lm = tree[cur].rm = tree[cur].sum = 0;
if(l == r) return;
int mid = (r + l) >> 1;
build(l, mid, cur << 1);
build(mid + 1, r, cur << 1 | 1);
}
void pushup(int cur) {
tree[cur].maxx = max(0LL, max(tree[cur << 1].maxx, tree[cur << 1 | 1].maxx));
tree[cur].maxx = max(tree[cur].maxx, max(0LL, tree[cur << 1].rm) + max(0LL, tree[cur << 1 | 1].lm));
tree[cur].lm = max(0LL, max(tree[cur << 1].lm, tree[cur << 1].sum + tree[cur << 1 | 1].lm));
tree[cur].rm = max(0LL, max(tree[cur << 1 | 1].rm, tree[cur << 1 | 1].sum + tree[cur << 1].rm));
tree[cur].sum = tree[cur << 1].sum + tree[cur << 1 | 1].sum;
}
void update(int pos, int cur, int val) {
if(tree[cur].l == tree[cur].r) {
tree[cur].maxx += val;
tree[cur].lm += val;
tree[cur].rm += val;
tree[cur].sum += val;
return;
}
if(pos <= tree[cur << 1].r) update(pos, cur << 1, val);
else update(pos, cur << 1 | 1, val);
pushup(cur);
}
int main() {
int T, pos;
ll ans;
scanf("%d", &T);
while(T--) {
scanf("%d", &n);
len1 = len2 = 0;
for(int i = 1; i <= n; i++) scanf("%d %d %d", &p[i].x, &p[i].y, &p[i].w), b[++len1] = p[i].x;
sort(b + 1, b + 1 + len1);
len1 = unique(b + 1, b + 1 + len1) - (b + 1);
for(int i = 1; i <= n; i++) p[i].x = lower_bound(b + 1, b + 1 + len1, p[i].x) - b;
for(int i = 1; i <= n; i++) b[++len2] = p[i].y;
sort(b + 1, b + 1 + len2);
len2 = unique(b + 1, b + 1 + len2) - (b + 1);
for(int i = 1; i <= n; i++) p[i].y = lower_bound(b + 1, b + 1 + len2, p[i].y) - b;
sort(p + 1, p + 1 + n);
ans = 0;
for(int i = 1; i <= len2; i++) {
for(int j = n; j >= 1; j--) {
if(p[j].y <= i) {
pos = j;
break;
}
}
build(1, len1, 1);
for(int j = i; j >= 1; j--) {
while(pos && p[pos].y >= j) {
update(p[pos].x, 1, p[pos].w);
pos--;
}
ans = max(ans, tree[1].maxx);
}
}
printf("%lld\n", ans);
}
return 0;
}