题解:
枚举上下边界,用线段树维护区间最大子段和。
具体的,首先枚举下界,固定下界的情况下,上界的枚举与计算答案并更新可以 O(n) 完成。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define int ll
#define PI acos(-1.0)
#define INF 0x3f3f3f3f3f3f3f3f
#define P pair<int, int>
#define fastio ios::sync_with_stdio(false), cin.tie(0)
const int mod = 998244353;
const int M = 1000000 + 10;
const int N = 2000 + 10;
int t, n;
int ma[N<<2], lma[N<<2], rma[N<<2], sum[N<<2];
struct node {
int x, y, w;
bool operator < (const node &cmp) const {
return y < cmp.y;
}
} no[N];
int cpx[N], cntx, cpy[N], cnty;
void build(int l = 1, int r = cntx, int rt = 1)
{
ma[rt] = lma[rt] = rma[rt] = sum[rt] = 0;
if(l == r) return ;
int mid = (l + r) >> 1;
build(l, mid, rt << 1);
build(mid + 1, r, rt << 1 | 1);
}
void add(int pos, int val, int l = 1, int r = cntx, int rt = 1)
{
if(l == r) {
sum[rt] += val;
ma[rt] += val;
lma[rt] += val;
rma[rt] += val;
return ;
}
int mid = (l + r) >> 1;
if(pos <= mid) add(pos, val, l, mid, rt << 1);
else add(pos, val, mid + 1, r, rt << 1 | 1);
lma[rt] = max(lma[rt << 1], sum[rt << 1] + lma[rt << 1 | 1]);
rma[rt] = max(rma[rt << 1 | 1], sum[rt << 1 | 1] + rma[rt << 1]);
ma[rt] = max(max(ma[rt << 1], ma[rt << 1 | 1]), rma[rt << 1] + lma[rt << 1 | 1]);
sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
}
signed main()
{
fastio;
cin >> t;
while(t --) {
cin >> n;
for(int i = 1; i <= n; i ++) {
cin >> no[i].x >> no[i].y >> no[i].w;
cpx[i] = no[i].x, cpy[i] = no[i].y;
}
sort(cpx + 1, cpx + 1 + n);
cntx = unique(cpx + 1, cpx + 1 + n) - cpx - 1;
sort(cpy + 1, cpy + 1 + n);
cnty = unique(cpy + 1, cpy + 1 + n) - cpy - 1;
for(int i = 1; i <= n; i ++) {
no[i].x = lower_bound(cpx + 1, cpx + 1 + cntx, no[i].x) - cpx;
no[i].y = lower_bound(cpy + 1, cpy + 1 + cnty, no[i].y) - cpy;
}
sort(no + 1, no + 1 + n);
int ans = 0;
for(int i = 1; i <= cnty; i ++) {
build();
int now = 1;
while(now <= n && no[now].y < i) now ++;
for(int j = i; j <= cnty; j ++) {
while(now <= n && no[now].y == j) {
add(no[now].x, no[now].w);
now ++;
}
ans = max(ans, ma[1]);
}
}
cout << ans << endl;
}
return 0;
}
/*
Rejoicing in hope, patient in tribulation.
*/