题目链接
题意
一个直角坐标系上有许多点,每个点都有一个权值。
选择一个
w
w
w 宽度,
h
h
h 高度的矩阵,能框住最大权值是多少。(在框边缘的不算)
思路
在框边缘的不算,可以将可覆盖区域边长减小1,边缘就能被包含了。
固定点可以知道每个框的右边缘、上边缘需要在的范围。
用扫描线的思想,将每个点拆分
<
x
,
y
,
y
+
h
−
1
,
权
值
>
<x,y,y+h-1,权值>
<x,y,y+h−1,权值> 和
<
x
+
w
,
y
,
y
+
h
−
1
,
−
权
值
>
<x+w,y,y+h-1,-权值>
<x+w,y,y+h−1,−权值>,离散化,按x轴排序,再维护y轴的区间最大值即可。
代码
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <vector>
using namespace std;
#define ll long long
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
struct Node
{
ll x, y1, y2, f;
Node(){}
Node(ll a, ll b, ll c, ll d):x(a),y1(b),y2(c),f(d){}
bool operator <(const Node &a) const
{
return x < a.x;
}
}e[20005];
vector<ll> lis;
ll maxn[20005 << 2], lazy[20005 << 2];
void pushdown(ll rt)
{
if(lazy[rt])
{
lazy[rt<<1] += lazy[rt];
lazy[rt<<1|1] += lazy[rt];
maxn[rt<<1] += lazy[rt];
maxn[rt<<1|1] += lazy[rt];
lazy[rt] = 0;
}
}
void updata(ll rt, ll l, ll r, ll ql, ll qr, ll num)
{
if(ql <= l && r <= qr)
{
maxn[rt] += num;
lazy[rt] += num;
return;
}
pushdown(rt);
ll mid = (l+r) >> 1;
if(ql <= mid) updata(lson,ql,qr,num);
if(qr > mid) updata(rson,ql,qr,num);
maxn[rt] = max(maxn[rt<<1], maxn[rt<<1|1]);
}
int main()
{
ll n, w, h;
while(~scanf("%lld%lld%lld",&n,&w,&h))
{
lis.clear();
for(ll i = 0; i < n; ++i)
{
ll x, y, c;
scanf("%lld%lld%lld",&x,&y,&c);
e[i<<1] = Node(x,y,y+h-1,c);
lis.push_back(y);
e[i<<1|1] = Node(x+w,y,y+h-1,-c);
lis.push_back(y+h-1);
}
n <<= 1;
sort(e,e+n);
sort(lis.begin(),lis.end());
lis.erase(unique(lis.begin(),lis.end()), lis.end());
lis.insert(lis.begin(),lis[0]-1);
ll ans = 0;
memset(lazy,0,sizeof(lazy));
memset(maxn,0,sizeof(maxn));
for(ll i = 0; i < n; ++i)
{
ll l = lower_bound(lis.begin(),lis.end(),e[i].y1) - lis.begin();
ll r = lower_bound(lis.begin(),lis.end(),e[i].y2) - lis.begin();
updata(1,1,n,l,r,e[i].f);
ans = max(ans, maxn[1]);
}
printf("%lld\n",ans);
}
return 0;
}