一个平面上有 n 个点,每个点有一个对应的权值,其他点的权值都是0,让你选一个矩形,要求矩形内所有点的权值最大。
枚举上边界,对于每一行的点,将他依此加入到线段树中,同时更新最大值。时间复杂度
大力区间和并,查询的时候还要同时查一下跨左右区间的最大值。
#include <bits/stdc++.h>
#define lson left,mid,k<<1
#define rson mid+1,right,k<<1|1
#define imid int mid=(que[k].l+que[k].r)/2;
#define ll long long
#define sc scanf
#define pr printf
using namespace std;
const int MAXN = 2005;
struct note
{
int x;
int y;
ll val;
}in[MAXN];
int t1[MAXN], t2[MAXN];
struct node
{
int l;
int r;
ll lmaxn;
ll rmaxn;
ll maxn;
ll sum;
}que[MAXN * 4];
int n, qq1, qq2;
void up(int k)
{
que[k].sum = que[k << 1].sum + que[k << 1 | 1].sum;
que[k].maxn = max({ que[k << 1].maxn,que[k << 1 | 1].maxn,que[k << 1].rmaxn + que[k << 1 | 1].lmaxn });
que[k].lmaxn = max(que[k << 1].lmaxn, que[k << 1].sum + que[k << 1 | 1].lmaxn);
que[k].rmaxn = max(que[k << 1 | 1].rmaxn, que[k << 1 | 1].sum + que[k << 1].rmaxn);
}
void build(int left = 1, int right = n, int k = 1)
{
que[k].l = left;
que[k].r = right;
if (left == right)
{
que[k].sum = 0;
que[k].maxn = 0;
que[k].lmaxn = 0;
que[k].rmaxn = 0;
return;
}
imid;
build(lson);
build(rson);
up(k);
}
void update(int pos, ll val, int k)
{
if (que[k].l == que[k].r)
{
que[k].sum += val;
que[k].maxn += val;
que[k].lmaxn += val;
que[k].rmaxn += val;
return;
}
imid;
if (pos <= mid)
update(pos, val, k << 1);
if (pos > mid)
update(pos, val, k << 1 | 1);
up(k);
}
ll queryl(int left, int right, int k)
{
if (left == que[k].l && que[k].r == right)
return que[k].lmaxn;
imid;
if (right <= mid)
return queryl(left, right, k << 1);
else if (left > mid)
return queryl(left, right, k << 1 | 1);
else
return max({ queryl(lson), que[k << 1].maxn + queryl(rson) });
}
ll queryr(int left, int right, int k)
{
if (left == que[k].l && que[k].r == right)
return que[k].rmaxn;
imid;
if (right <= mid)
return queryr(left, right, k << 1);
else if (left > mid)
return queryr(left, right, k << 1 | 1);
else
return max({ queryr(rson), queryr(lson) + que[k << 1 | 1].maxn });
}
ll query(int left, int right, int k)
{
if (left == que[k].l && que[k].r == right)
return que[k].maxn;
imid;
if (right <= mid)
return query(left, right, k << 1);
else if (left > mid)
return query(left, right, k << 1 | 1);
else
return max({ query(lson),query(rson),queryr(lson) + queryl(rson) });
}
int main()
{
int T;
sc("%d", &T);
while (T--)
{
scanf("%d", &n);
for (int i = 1; i <= n; i++)
{
scanf("%d%d%lld", &in[i].x, &in[i].y, &in[i].val);
t1[i] = in[i].x;
t2[i] = in[i].y;
}
sort(t1 + 1, t1 + 1 + n);
qq1 = unique(t1 + 1, t1 + 1 + n) - t1 - 1;
for (int i = 1; i <= n; i++)
in[i].x = lower_bound(t1 + 1, t1 + 1 + qq1, in[i].x) - t1;
sort(t2 + 1, t2 + 1 + n);
qq2 = unique(t2 + 1, t2 + 1 + n) - t2 - 1;
for (int i = 1; i <= n; i++)
in[i].y = lower_bound(t2 + 1, t2 + 1 + qq2, in[i].y) - t2;
sort(in + 1, in + 1 + n, [](note q, note w) {
if (q.y == w.y)
return q.x < w.x;
return q.y < w.y;
});
ll ans = 0;
for (int i = 1; i <= qq2; i++)
{
build(1, qq1, 1);
for (int j = 1; j <= n; j++)
{
if (in[j].y < i)
continue;
if (in[j].y != in[j - 1].y)
{
ll res = query(1, qq1, 1);
ans = max(res, ans);
}
update(in[j].x, in[j].val, 1);
}
ll res = query(1, qq1, 1);
ans = max(res, ans);
}
pr("%lld\n", ans);
}
}
/*
1
9
1 1 1
1 2 1
1 3 1
2 1 1
2 2 -9
2 3 1
3 1 1
3 2 1
3 3 1
*/