poj12482 扫描线+lazy-tag

时间:2022-03-07 09:17:16

采用扫描线的思想,其实是区间更新的题目

题解链接https://blog.csdn.net/shiqi_614/article/details/7819232

注意处理细节:1)因为边框上的点不算,所以要当出边入边重合时,要先更新出边,再更新入边

       2)同理,在y轴上建立的线段树应该把坐标离散成互不相交的点,如(0,1),(1,2),(2,3)等开区间来代替[0,1],[1,2],[2,3],这样就能避免算入边框上的点。

          怎么使用开区间?如果更新的线段是[1,2],那么实际上只能覆盖住[1,1]所以只要在update的两个分支中修改即可

#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<map>
#define ll long long
using namespace std;
#include<algorithm>
#define maxn 40005
#define lson l,m,rt<<1
#define rson m,r,rt<<1|1
struct Seg{
ll x,y1,y2,c;
Seg(){}
Seg(ll a,ll b,ll c,ll d):x(a),y1(b),y2(c),c(d){}
bool operator<(const Seg& a)const{
if(x==a.x) return c<a.c;
return x<a.x;
}
}segs[maxn*]; int w,h;
ll tot,toty,data[maxn];
map<ll,int> mp;//哈希表
int Max[maxn<<],lazy[maxn<<];//在y轴上建立线段树
inline void pushup(int rt){
Max[rt]=max(Max[rt<<],Max[rt<<|]);
}
inline void pushdown(int rt){
if(lazy[rt]){
Max[rt<<]+=lazy[rt];
Max[rt<<|]+=lazy[rt];
lazy[rt<<]+=lazy[rt];
lazy[rt<<|]+=lazy[rt];
lazy[rt]=;
}
}
void update(int L,int R,int c,int l,int r,int rt){
if(L<=l && R>=r){
lazy[rt]+=c;
Max[rt]+=c;
return;
}
pushdown(rt);
int m=l+r>>;
if(L<m) update(L,R,c,lson);//离散化后要作为开区间处理
if(R>m) update(L,R,c,rson);
pushup(rt);
}
void init(){
toty=tot=;
mp.clear();
memset(Max,,sizeof Max);
memset(lazy,,sizeof lazy);
}
int main(){
ll n,a,b,c;
while(scanf("%lld%d%d",&n,&w,&h)==){
init();
for(int i=;i<=n;i++){
scanf("%lld%lld%lld",&a,&b,&c);
segs[tot++]=Seg(a,b,b+h,c);segs[tot++]=Seg(a+w,b,b+h,-c);
data[toty++]=b;data[toty++]=b+h;
}
sort(data,data+toty);
sort(segs,segs+tot);
toty=unique(data,data+toty)-data;
for(int i=;i<toty;i++) mp[data[i]]=i;//用map(哈希)离散化 int mx=;
for(int i=;i<tot;i++){
update(mp[segs[i].y1],mp[segs[i].y2],segs[i].c,,toty,);
mx=max(mx,Max[]);
}
printf("%d\n",mx);
}
return ;
}