P1502 窗口的星星 离散化+扫描线
Posted 昵称很长很长真是太好了
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P1502 窗口的星星 离散化+扫描线相关的知识,希望对你有一定的参考价值。
题意:
一个二维平面上有些点有权值。
问给你一个H*W的窗口,问窗口星星亮度总和的最大值。
H
∗
W
范
围
:
1
e
6
H*W 范围:1e6
H∗W范围:1e6
坐
标
范
围
:
1
e
9
坐标范围:1e9
坐标范围:1e9
星
星
数
目
:
1
e
4
星星数目:1e4
星星数目:1e4
题解:
我们考虑一维的情况。
假设一个序列
a
a
a,给你你最多可以选择连续长度为
l
e
n
len
len序列段,问可以选择出最大的序列和为多少。
我们可以将这个(单点修改,区间查询)的问题给转换成,(区间修改,单点查询)问题。
初始化一个新数组
b
b
b为0
对于第
i
i
i个值来说,我们把
b
b
b的第
i
i
i到第
i
+
l
e
n
i+len
i+len的值加上
a
[
i
]
a[i]
a[i]
然后查询b序列的最大值即为答案
同理我们可以得出在二维平面上的结论。
那么我们把该点
(
i
,
j
)
(i,j)
(i,j)权值,在
[
(
i
,
i
+
W
)
,
(
j
,
j
+
H
)
]
[(i,i+W),(j,j+H)]
[(i,i+W),(j,j+H)]的范围内每个点都加上。然后就是查询这个新生成矩阵的最大值的点是哪个即可。
如何查询?
扫描线。
说是扫描线,不过这个扫描线是统计最大值点的,并不是统计面积的。
所以原来扫描线的模板不可以照搬。
也可以理解为线段树+离散化。
还有需要灵活处理的一点就是边框上的点是算不进去的,那你把窗口的长宽各减去1即可。
比较坑的一点:对 x 坐标进行升序排序时,将 val 值按降序排序,这样才能处理两个矩形贴合的情况。
代码:
#include<bits/stdc++.h>
#define endl '\\n'
//#define int long long
using namespace std;
const int maxn=4e5;
struct L
int x;
int y1,y2;
int flag;
bool operator <(const L & a)const
if(x!=a.x) return x<a.x;
else return flag>a.flag;
line[maxn];
int v[maxn];
int tree[maxn],lazy[maxn];
void push_down(int node)
if(lazy[node])
tree[node<<1]+=lazy[node];
tree[node<<1|1]+=lazy[node];
lazy[node<<1]+=lazy[node];
lazy[node<<1|1]+=lazy[node];
lazy[node]=0;
void update(int node,int start,int ends,int l,int r,int val)
if(l<=start&&ends<=r)
tree[node]+=val;
lazy[node]+=val;
return;
push_down(node);
int mid=(start+ends)>>1;
if(l<=mid) update(node<<1,start,mid,l,r,val);
if(mid<r) update(node<<1|1,mid+1,ends,l,r,val);
tree[node]=max(tree[node<<1],tree[node<<1|1]);
signed main()
ios::sync_with_stdio(false);
cin.tie(0);
int t;
cin>>t;
while(t--)
int n,h,w;
cin>>n>>w>>h;
for(int i=1;i<=n;i++)
int x,y,z;
cin>>x>>y>>z;
int x1=x+w-1;
int y1=y+h-1;
v[i]=y,v[i+n]=y1;
line[i]=x,y,y1,z;
line[i+n]=x1,y,y1,-z;
sort(v+1,v+1+2*n);
sort(line+1,line+1+2*n);
int tot=unique(v+1,v+1+2*n)-v-1;
for(int i=1;i<=2*n;i++)
int x=lower_bound(v+1,v+tot+1,line[i].y1)-v;
int y=lower_bound(v+1,v+tot+1,line[i].y2)-v;
line[i].y1=x;
line[i].y2=y;
int ans=0;
for(int i=1;i<=2*n;i++)
update(1,1,tot,line[i].y1,line[i].y2,line[i].flag);
ans=max(ans,tree[1]);
memset(tree,0,sizeof tree);
memset(lazy,0,sizeof lazy);
cout<<ans<<endl;
以上是关于P1502 窗口的星星 离散化+扫描线的主要内容,如果未能解决你的问题,请参考以下文章