一个小小的bug搞了将近两天,郁闷shi了
平面上有很多点,每个点有一个权值,给定一个矩形,求出用这个矩形去套时所能同时套住的点的权值的和的最大值
转换成线段树:以每个点为左下角向右延伸转换成一个矩形,对x轴建树,一个点就相当于两条线段,一条权值为v,另一条权值为-v,线段树维护总的区间内最大的覆盖次数,把每次的Max[1]与ans比较,能更新就更新。
具体为什么这样,用笔和纸画画,仔细想想应该能想出来,我开始也是不清楚,结果在纸上把各种情况一模拟,就清楚了
#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
*/
下面是另一种比较通用的写法
#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; }