poj 2482 线段树 扫描线

一个小小的bug搞了将近两天,郁闷shi了

平面上有很多点,每个点有一个权值,给定一个矩形,求出用这个矩形去套时所能同时套住的点的权值的和的最大值

转换成线段树:以每个点为左下角向右延伸转换成一个矩形,对x轴建树,一个点就相当于两条线段,一条权值为v,另一条权值为-v,线段树维护总的区间内最大的覆盖次数,把每次的Max[1]与ans比较,能更新就更新。

具体为什么这样,用笔和纸画画,仔细想想应该能想出来,我开始也是不清楚,结果在纸上把各种情况一模拟,就清楚了

View Code
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int maxn = 20010;
int cover[maxn<<2],Max[maxn<<2];
struct seg{
double l,r,h;
int flag;
seg(){}
seg(double _l,double _r,double _h,int _flag):l(_l),r(_r),h(_h),flag(_flag){}
bool operator <(const seg &cmp) const {
if(h==cmp.h) return flag<cmp.flag;
return h<cmp.h;
}
}horizontal_seg[maxn];
int ans;
double x[maxn];
int max(int a,int b){
return a>b?a:b;
}
void pushdown(int rt){
if(cover[rt]){
cover[rt<<1]+=cover[rt];
cover[rt<<1|1]+=cover[rt];
Max[rt<<1]+=cover[rt];
Max[rt<<1|1]+=cover[rt];
cover[rt]=0;
}
}
void pushup(int rt){
Max[rt]=max(Max[rt<<1],Max[rt<<1|1]);
}
void update(int L,int R,int c,int l,int r,int rt){
if(L<=l&&r<=R){
cover[rt]+=c;
Max[rt]+=c;
return ;
}
pushdown(rt);
int m=(l+r)>>1;
if(L<=m) update(L,R,c,lson);
if(R>m) update(L,R,c,rson);
pushup(rt);
}
int bin(double key,int n,double x[]){
int l=0,r=n-1,mid,best=-1;
while(l<=r){
mid=(l+r)>>1;
if(x[mid]<=key){
best=mid;
l=mid+1;
}
else r=mid-1;
}
return best;
}
int main(){
freopen("in.txt","r",stdin);
freopen("b.txt","w",stdout);
int n,i,j,k,c;
double W,H;
double a,b;
while(scanf("%d%lf%lf",&n,&W,&H)!=EOF){
int tot=0;
ans=0;
memset(cover,0,sizeof(cover));
memset(Max,0,sizeof(Max));
for(i=1;i<=n;i++){
scanf("%lf%lf%d",&a,&b,&c);
x[tot]=a;
horizontal_seg[tot++]=seg(a,a+W,b,c);
x[tot]=a+W;
horizontal_seg[tot++]=seg(a,a+W,b+H,-c);
}
sort(x,x+tot);
for(i=1,k=1;i<tot;i++)
if(x[i]!=x[i-1]) x[k++]=x[i];
sort(horizontal_seg,horizontal_seg+tot);
for(i=0,j=0;i<tot-1;i++){
int left=bin(horizontal_seg[i].l,k,x);
int right=bin(horizontal_seg[i].r,k,x)-1;
update(left,right,horizontal_seg[i].flag,0,k-1,1);
if(Max[1]>ans) ans=Max[1];
}
printf("%d\n",ans);
}
return 0;
}
/*
4 24 83
78 46 87
46 82 50
20 33 36
8 5 62
*/

 

下面是另一种比较通用的写法

View Code
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int maxn = 20010;
int cover[maxn<<2],Max[maxn<<2];
struct Point{
    double x,y;
    int c;
    bool operator < (const Point &cmp)const{
        return y<cmp.y;
    }
}p[maxn];
int ans;
double x[maxn];
inline int max(int a,int b){
    return a>b?a:b;
}
void pushdown(int rt){
    if(cover[rt]){
        cover[rt<<1]+=cover[rt];
        cover[rt<<1|1]+=cover[rt];
        Max[rt<<1]+=cover[rt];
        Max[rt<<1|1]+=cover[rt];
        cover[rt]=0;
    }
}
void pushup(int rt){
    Max[rt]=max(Max[rt<<1],Max[rt<<1|1]);
}
void update(int L,int R,int c,int l,int r,int rt){
    if(L<=l&&r<=R){
        cover[rt]+=c;
        Max[rt]+=c;
        return ;
    }
    pushdown(rt);
    int m=(l+r)>>1;
    if(L<=m) update(L,R,c,lson);
    if(R>m) update(L,R,c,rson);
    pushup(rt);
}
int main(){
    int n,i,j,k,c;
    double W,H;
    double a,b;
    while(scanf("%d%lf%lf",&n,&W,&H)!=EOF){
        int tot=0;
        ans=0;
        memset(cover,0,sizeof(cover));
        memset(Max,0,sizeof(Max));
        for(i=0;i<n;i++){
            scanf("%lf%lf%d",&p[i].x,&p[i].y,&p[i].c);
            x[tot++]=p[i].x;
            x[tot++]=p[i].x+W;
        }
        sort(p,p+n);
        sort(x,x+tot);
        k=unique(x,x+tot)-x;
        for(i=0,j=0;i<n;i++){
            int left=lower_bound(x,x+k,p[i].x)-x;
            int right=lower_bound(x,x+k,p[i].x+W)-x-1;
            update(left,right,p[i].c,0,k-1,1);
            while(j <= i && p[i].y-p[j].y >= H) {
                left=lower_bound(x,x+k,p[j].x)-x;
                right=lower_bound(x,x+k,p[j].x+W)-x-1;
                update(left,right,-p[j].c,0,k-1,1);
                j++;
            }
            if(Max[1]>ans) ans=Max[1];
        }
        printf("%d\n",ans);
    }
    return 0;
}
posted @ 2012-02-10 22:03  Because Of You  Views(877)  Comments(0)    收藏  举报