其实两个多月之前写过一篇,但是那时候的水平怎么能和现在相比,恰好前几天鸽了一道扫描线的题,所以今天来补上;
POJ2482
POJ1151
前面一个是数星星,后面一个是亚特兰蒂斯,两题其实都是属于扫描线的一个模板题啊,数星星那个属于是找最大值的版本,亚特兰蒂斯那个属于是找和的版本;
扫描线其实就是一个平面上有一些线,无非你要求出关于这些线的一个信息罢了。
你先定下一个坐标表示你当前的一个线段树的一个含义,然后把另一个维度当成是时间轴,你就根据另一个维度去操作就好了;
首先如果说那些点的横纵坐标的值域都是不需要离散化的,那么显然是很好操作的,直接乱改就行了;
那么如果值域很离谱的话,我们无非是加上一个离散化是吧;
这里讲一种别人那里看来的很好的一种离散化的方法,就是说我们一般的离散化,在线段树中呢,一个节点的l和r代指的都是数组里面的坐标,然后每次都要进数组再进行一个操作,我从别人那里看来的呢,一个节点的l和r就代指真实的坐标,然后用的时候加上去一下就好了,我个人认为,后面一种写法可能更能贴近我的使用习惯;
然后亚特兰蒂斯那题有个地方要注意,为什么要打上一个tag;
平时求区间和的线段树是不用打tag的,那是因为那是可以随便加的,而这个打上tag是因为不能随便加,有了覆盖之后就不能乱搞了;
附上数星星的代码,这么漂亮的代码,当然是copy的啦;
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define int long long
typedef long long ll;
typedef pair<int,int> PII;
const int INF = 0x3f3f3f3f;
const int N = 2e5+7;
const int M = 2007;
int n,w,h,a[N],cnt;
struct Seg{
int lc,rc;
int len;
int lz;
#define trl(x) tree[x].lc
#define trr(x) tree[x].rc
#define tlen(x) tree[x].len
#define tlz(x) tree[x].lz
}tree[N<<1];
struct node{
int x,y1,y2,f;
}p[N];
bool cmp(node xa,node yb) {
return xa.x < yb.x || ( xa.x == yb.x && xa.f < 0 ) ;
}
inline void add(int x,int y,int k) {
p[cnt].x = x;
p[cnt].y1 = y;
p[cnt].y2 = y + h;
p[cnt++].f = k;
}
inline void build(int p,int l,int r){
trl(p) = a[l];
trr(p) = a[r];
tlz(p) = tlen(p) = 0;
if(r - l == 1) return;
int mid = (l+r) >> 1;
build(p<<1,l,mid);
build(p<<1|1,mid,r);
}inline void change(int p,int l,int r,int k){
if(l <= trl(p) && trr(p) <= r){
tlz(p) += k;
tlen(p) += k;
return;
}
if(l < trr(p<<1) ) change(p<<1,l,min(trr(p),r),k);
if(r > trl(p<<1|1))change(p<<1|1,max(l,trl(p)),r,k);
tlen(p) = max(tlen(p<<1),tlen(p<<1|1)) + tlz(p);
}
int main()
{
while(scanf("%lld%lld%lld",&n,&w,&h)!=EOF){
cnt = 1;
int num = 1;
for(int i=1;i<=n;i++){
int x,y,k;
scanf("%lld%lld%lld",&x,&y,&k);
add(x,y,k);
add(x-w,y,-k);
a[num++] = y;
a[num++] = y+h;
}
sort(a+1,a+num);
int ass = 0;
num = unique(a+1,a+num) - (a+1);
sort(p+1,p+cnt,cmp);
build(1,1,num);
for(int i=1;i<=cnt;i++){
change(1,p[i].y1,p[i].y2,p[i].f);
if(p[i].f > 0){
ass = max(ass,tlen(1));
}
}
printf("%lld\n",ass);
}
return 0;
}