题意:给出n个矩形的位置,问重叠奇数个矩形的面积之和
做法:
和一般的线段树不一样,要将原来的[l,mid],[mid+1,r],改成[l,mid],[mid,r],这样才不能改变其总长度。用线段树做一下区间更新即可。记住打laz标记。
#include<bits/stdc++.h>
#define lson rt<<1
#define rson rt<<1|1
using namespace std;
typedef long long ll;
const int maxn=100005;
struct seg{
ll l,r,h;
}se[maxn*2];
ll siz[maxn*8];
bool laz[maxn*8];
bool cmp(seg a,seg b){
return a.h<b.h;
}
ll n,k,m,X[maxn*2];
ll fin(ll x){
ll ans=lower_bound(X,X+m,x)-X;
return ans;
}
void Switch(ll l,ll r,ll rt){
ll all=X[r]-X[l];
siz[rt]= all-siz[rt];
}
void pushdown(ll l,ll r,ll rt){
if(laz[rt]){
ll mid=(l+r)/2;
Switch(l,mid,lson);
Switch(mid,r,rson);
laz[lson]^=1; laz[rson]^=1;
laz[rt]=0;
}
}
void update(ll ql,ll qr,ll l,ll r,ll rt){
if(l>=ql&&r<=qr){
Switch(l,r,rt);
laz[rt]^=1;
return ;
}
pushdown(l,r,rt);
ll mid=(l+r)/2;
if(ql<mid) update(ql,qr,l,mid,lson);
if(qr>mid) update(ql,qr,mid,r,rson);
siz[rt]=siz[lson]+siz[rson];
}
int main(){
scanf("%d",&n);
k=1;
for(int i=1;i<=n;i++,k+=2){
ll x1,x2,y1,y2;
scanf("%lld%lld%lld%lld",&x1,&y1,&x2,&y2);
X[k]=x1,X[k+1]=x2;
se[k].l=x1,se[k].r=x2,se[k].h=y1;
se[k+1].l=x1,se[k+1].r=x2,se[k+1].h=y2;
}
k--;
X[0]=-1;
sort(se+1,se+1+k,cmp);
sort(X+1,X+1+k);
m=0;
for(int i=1;i<=k;i++){
if(X[i]!=X[i-1]) X[++m]=X[i];
}
ll ans=0;
for(int i=1;i<k;i++){
int l=fin(se[i].l);
int r=fin(se[i].r);
update(l,r,1,m,1);
ans=(ans+siz[1]*(se[i+1].h-se[i].h));
//printf("i=%d ans=%.2f\n",i,ans);
}
printf("%lld\n",ans);
return 0;
}
poj 2482 http://poj.org/problem?id=2482
同样的左闭右开区间。累的啊。。
#include<cstdio>
#include<algorithm>
#include<cstring>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define lson rt<<1
#define rson rt<<1|1
typedef long long ll;
using namespace std;
const int maxn=10005;
struct seg{
ll l,r,h,v;
seg(){}
seg(ll l,ll r,ll h,ll v):l(l),r(r),h(h),v(v){}
bool operator < (const seg &a)const{
if(a.h==h) return v<a.v;
return h<a.h;
}
} se[maxn*2];
int n,m;
ll H,W;
ll sum[maxn<<3],laz[maxn<<3],X[maxn*2];
void deal(int rt,ll v){
sum[rt]+=v;
laz[rt]+=v;
}
void push_down(int rt){
if(laz[rt]){
deal(lson,laz[rt]);
deal(rson,laz[rt]);
laz[rt]=0;
}
}
void update(int ql,int qr,int l,int r,int rt,ll v){
if(ql<=l&&r<=qr){
deal(rt,v);
return ;
}
push_down(rt);
int mid=(l+r)/2;
if(ql<mid) update(ql,qr,l,mid,lson,v);
if(qr>mid) update(ql,qr,mid,r,rson,v);
sum[rt]=max(sum[lson],sum[rson]);
}
int main(){
while(~scanf("%d%lld%lld",&n,&W,&H)){
memset(sum,0,sizeof(sum));
memset(laz,0,sizeof(laz));
rep(i,1,n){
ll xx,yy,bri;
scanf("%lld%lld%lld",&xx,&yy,&bri);
se[i]=seg(xx,xx+W,yy,bri);
se[i+n]=seg(xx,xx+W,yy+H,-bri);
X[i]=xx,X[i+n]=xx+W;
}
n*=2;
sort(se+1,se+1+n);
sort(X+1,X+1+n);
m=unique(X+1,X+1+n)-X-1;
ll ans=0;
rep(i,1,n){
int L=lower_bound(X+1,X+1+m,se[i].l)-X;
int R=lower_bound(X+1,X+1+m,se[i].r)-X;
update(L,R,1,m,1,se[i].v);
ans=max(ans,sum[1]);
}
printf("%lld\n",ans);
}
return 0;
}