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;

}

你可能感兴趣的:(poj)