题意
在平面上有 \(n\) 个点, 已知每个点的 \((x, y)\) 及其权值 \(c\),现要求在直线 \(y = x\) 上选择正方形的左下角与右上角,使得正方形(含边界)所覆盖点的权值和 与 边长的差值最大,边长可为0,求最大差值并输出可行方案。
思路
既然正方形的一条对角线在 \(y = x\) 上,则可以在将点坐标离散化之后枚举右上角的坐标 \(y\) ,求 \([1, y]\) 范围内区间和 - 边长的最大值及其下标。
可以采用线段树维护差值的最大值及其下标。
线段树使用
假设点的权值和为 \(sum\) , 正方形左下角坐标为 \((x, x)\) ,右上角坐标为\((y, y)\) ,则最终答案计算公式为 $ans = sum - (y-x) = sum + x - y $ 。
将所有点的坐标离散化之后,线段树的叶子结点初值赋值为对应的 \(x\) ,其余则为正常维护区间和的最大值及其下标,query出的最大值即为 \(sum+x\) ,减去所枚举的 \(y\) 即为对应 \(ans\)
Code
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 1e6+10; int n; int hsy[maxn<<1], pn; int x[maxn], y[maxn], c[maxn]; ll mx, pos; vector<int> g[maxn<<1]; struct node { int l, r, pos; ll mx, lazy; }tr[maxn<<2]; #define lson i<<1 #define rson i<<1|1 void pushup(int i) { if(tr[lson].mx > tr[rson].mx) tr[i].mx = tr[lson].mx, tr[i].pos = tr[lson].pos; else tr[i].mx = tr[rson].mx, tr[i].pos = tr[rson].pos; } void pushdown(int i) { if(!tr[i].lazy) return; tr[lson].mx += tr[i].lazy; tr[lson].lazy += tr[i].lazy; tr[rson].mx += tr[i].lazy; tr[rson].lazy += tr[i].lazy; tr[i].lazy = 0; } void build(int l, int r, int i) { tr[i] = node{l, r, l, 0, 0}; if(l == r) { tr[i].mx = hsy[l]; tr[i].pos = l; return; } int mid = l+r >> 1; build(l, mid, lson); build(mid+1, r, rson); pushup(i); } void update(int l, int r, ll val, int i) { if(l <= tr[i].l && tr[i].r <=r ) { tr[i].mx += val; tr[i].lazy += val; return; } pushdown(i); int mid = tr[i].l+tr[i].r >> 1; if(l <= mid) update(l, r, val, lson); if(mid < r) update(l, r, val, rson); pushup(i); } void query(int l, int r, int i) { if(l <= tr[i].l && tr[i].r <= r) { if(tr[i].mx > mx) { mx = tr[i].mx; pos = tr[i].pos; } return; } pushdown(i); int mid = tr[i].l+tr[i].r>>1; if(l <= mid) query(l, r, lson); if(r > mid) query(l, r, rson); } int main() { scanf("%d", &n); for (int i = 1; i <= n; ++i) { scanf("%d%d%d", x+i, y+i, c+i); if(x[i] > y[i]) swap(x[i], y[i]); hsy[++pn] = x[i]; hsy[++pn] = y[i]; } sort(hsy+1, hsy+1+pn); pn = unique(hsy+1, hsy+1+pn) - hsy-1; build(1, pn, 1); for (int i = 1; i <= n; ++i) { x[i] = lower_bound(hsy+1, hsy+1+pn, x[i]) - hsy; y[i] = lower_bound(hsy+1, hsy+1+pn, y[i]) - hsy; g[y[i]].emplace_back(i); } ll ans = 0, ansx = 2e9, ansy = 2e9; for (int i = 1; i <= pn; ++i) { for (auto v: g[i]) update(1, x[v], c[v], 1); mx = pos = 0; query(1, i, 1); mx -= hsy[i]; if(mx > ans) { ans = mx; ansx = hsy[pos]; ansy = hsy[i]; } } printf("%lld\n%lld %lld %lld %lld\n", ans, ansx, ansx, ansy, ansy); return 0; }