题面 :
题目链接 :
http://acm.hdu.edu.cn/showproblem.php?pid=6638
题目大意 :
给你 N 个点的坐标(X , Y)和权值(W) , 要求你找出一个矩形使得矩形内的点的权值和最大 , 问这个最大权值和为多少
解题思路 :
套路题
一个矩形有上下左右四条边,如果直接枚举四条边,复杂度为 N ^ 4 不可行
如果枚举上下(左右)两条边,再对上下(左右)两边之间的点 dp 求最大连续子段和,复杂度为 N ^ 3 ,还是不可行
如果枚举上下两条边,再对上下两边之间的点建立线段树维护最大连续子段和,操作如下 :
下边每枚举一次重新建立一棵树,上边每枚举一次将边上的点的权值插入线段树中点的横坐标的位置
那么复杂度为 N ^ 2 log N , 可行 ( 因为 X , Y 很大所以要先对 X , Y 离散化一下 )
AC_Code :
#include<bits/stdc++.h>
#define int long long
#define ll long long
using namespace std;
const int N = 2e3 + 10;
struct Segment_tree
{
ll l , r;
ll sum , lmax , rmax , ans;
} tree[N << 2];
void push_up(ll rt)
{
tree[rt].sum = tree[rt << 1].sum + tree[rt << 1 | 1].sum;
tree[rt].lmax = max(tree[rt << 1].lmax , tree[rt << 1].sum + tree[rt << 1 | 1].lmax);
tree[rt].rmax = max(tree[rt << 1 | 1].rmax , tree[rt << 1 | 1].sum + tree[rt << 1].rmax);
tree[rt].ans = max(tree[rt << 1].rmax + tree[rt << 1 | 1].lmax , max(tree[rt << 1].ans , tree[rt << 1 | 1].ans));
}
void build(ll l , ll r , ll rt , ll *aa)
{
tree[rt].l = l;
tree[rt].r = r;
if(tree[rt].l == tree[rt].r)
{
tree[rt].sum = aa[l];
tree[rt].lmax = aa[l];
tree[rt].rmax = aa[l];
tree[rt].ans = aa[l];
return ;
}
ll mid = l + r >> 1;
build(l , mid , rt << 1 , aa);
build(mid + 1 , r , rt << 1 | 1 , aa);
push_up(rt);
}
void update(ll pos , ll val , ll rt)
{
if(tree[rt].l == tree[rt].r)
{
tree[rt].ans += val;
tree[rt].sum += val;
tree[rt].lmax += val;
tree[rt].rmax += val;
return ;
}
ll mid = tree[rt].l + tree[rt].r >> 1;
if(pos <= mid)
update(pos , val , rt << 1);
if(pos > mid)
update(pos , val , rt << 1 | 1);
push_up(rt);
}
Segment_tree query_ans(ll l , ll r , ll rt)
{
if(l <= tree[rt].l && r >= tree[rt].r)
return tree[rt];
ll mid = tree[rt].l + tree[rt].r >> 1;
if(r <= mid)
return query_ans(l , r , rt << 1);
else if(l > mid)
return query_ans(l , r , rt << 1 | 1);
else
{
Segment_tree Ans , a , b;
a = query_ans(l , mid , rt << 1);
b = query_ans(mid + 1 , r , rt << 1 | 1);
Ans.sum = a.sum + b.sum;
Ans.lmax = max(a.lmax , a.sum + b.lmax);
Ans.rmax = max(b.rmax , a.rmax + b.sum);
Ans.ans = max(a.rmax + b.lmax , max(a.ans , b.ans));
return Ans;
}
}
struct node{
int x , y , w;
bool operator < (node const & a) const {
return x < a.x;
}
}a[N];
vector<node>vec[N];
int n , x[N] , y[N] , aa[N];
signed main()
{
ios::sync_with_stdio(false);
int t;
cin >> t;
while(t --)
{
cin >> n;
for(int i = 1 ; i <= n ; i ++)
{
cin >> a[i].x >> a[i].y >> a[i].w;
x[i] = a[i].x , y[i] = a[i].y;
}
sort(x + 1 , x + 1 + n) , sort(y + 1 , y + 1 + n);
int nx = unique(x + 1 , x + 1 + n) - x - 1 , ny = unique(y + 1 , y + 1 + n) - y - 1;
for(int i = 1 ; i <= n ; i ++)
{
a[i].x = lower_bound(x + 1 , x + 1 + nx , a[i].x) - x;
a[i].y = lower_bound(y + 1 , y + 1 + ny , a[i].y) - y;
vec[a[i].y].push_back(a[i]);
}
int ans = 0;
for(int i = 1 ; i <= ny ; i ++)
{
build(1 , nx , 1 , aa);
for(int j = i ; j <= ny ; j ++)
{
for(auto k : vec[j])
update(k.x , k.w , 1);
ans = max(ans , query_ans(1 , n , 1).ans);
}
}
cout << ans << '\n' ;
for(int i = 1 ; i <= ny ; i ++) vec[i].clear();
}
return 0;
}