hdu6638 Snowy Smile
题面 :
题目链接 :
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; }
凡所不能将我击倒的,都将使我更加强大