hdu1255(线段树——矩形面积交)

时间:2020-12-18 02:35:25

题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=1255

题意:求N个矩形中,求被覆盖至少俩次的面积和

分析:覆盖两次即col[rt]>=2就好。一开始将线段pushdown到叶子节点,根据col[rt]>=2才pushup上来,差点超时了,其实可以lazy标志,整段更新的,只是没想到而已。

用sum[rt][0]表示该节点rt代表的线段被覆盖一次的长度之和,则

if(col[rt])sum[rt][0]=pos[r+1]-pos[l];//整段被覆盖,全加上
else if(l==r)sum[rt][0]=0;//叶子节点没有子孙节点的覆盖传递上来,所以清零
else sum[rt][0]=sum[rt<<1][0]+sum[rt<<1|1][0];//加上子孙节点被覆盖着的长度

同理sum[rt][1]表示该节点rt代表的线段被覆盖两次的长度之和。则

if(col[rt]>1)sum[rt][1]=sum[rt][0];//整段被覆盖两次以上,全加上
else if(l==r)sum[rt][1]=0;//叶子节点没有子孙节点的覆盖两次的长度传递上来,故清零
else if(col[rt]==1)sum[rt][1]=sum[rt<<1][0]+sum[rt<<1|1][0];//加上之前子孙节点上被覆盖一次的长度,刚好共两次(覆盖一次的长度一定大于覆盖一次的)
else sum[rt][1]=sum[rt<<1][1]+sum[rt<<1|1][1];//加上子孙节点覆盖两次的总长度

如果题目求覆盖3次,4次都可以以此类推pushup上来。

成段更新(327ms)

#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstdlib>
#include <stack>
#include <vector>
#include <set>
#include <map>
#define LL long long
#define mod 10007
#define inf 0x3f3f3f3f
#define N 2015
#define FILL(a,b) (memset(a,b,sizeof(a)))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std; double pos[*N];
struct seg
{
double l,r,h;
int v;
seg(){}
seg(double l,double r,double h,int v):l(l),r(r),h(h),v(v){}
bool operator <(const seg a)const
{
return h<a.h;
}
}s[*N];
int n,col[N<<];
double sum[N<<][]; int bin(double key ,int low ,int high)
{
while(low <= high)
{
int mid=(low+high)>>;
if(pos[mid] == key)
return mid;
else if(pos[mid] < key)
low=mid+;
else
high=mid-;
}
return -;
}
void Pushup(int l,int r,int rt)
{
if(col[rt])sum[rt][]=pos[r+]-pos[l];
else if(l==r)sum[rt][]=;
else sum[rt][]=sum[rt<<][]+sum[rt<<|][]; if(col[rt]>)sum[rt][]=sum[rt][];
else if(l==r)sum[rt][]=;
else if(col[rt]==)sum[rt][]=sum[rt<<][]+sum[rt<<|][];
else sum[rt][]=sum[rt<<][]+sum[rt<<|][];
}
void update(int L,int R,int c,int l,int r,int rt)
{
if(L<=l&&r<=R)
{
col[rt]+=c;
Pushup(l,r,rt);
return;
}
int m=(l+r)>>;
if(L<=m)update(L,R,c,l,m,rt<<);
if(m<R)update(L,R,c,m+,r,rt<<|);
Pushup(l,r,rt);
} int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
int i,k;
for(i=,k=; i<n; i++)
{
double x1,y1,x2,y2;
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
pos[k]=x1;
s[k++]=seg(x1,x2,y1,);
pos[k]=x2;
s[k++]=seg(x1,x2,y2,-);
}
sort(pos,pos+k);
sort(s,s+k);
int m=;
for(i=; i<k; i++)
if(pos[i]!=pos[i-])
pos[m++]=pos[i];
double res=;
for(i=; i<k; i++)
{
int l=bin(s[i].l,,m-);
int r=bin(s[i].r,,m-)-;
update(l,r,s[i].v,,m-,);
res += sum[][]*(s[i+].h - s[i].h);
}
printf("%.2lf\n",res);
}
return ;
}

比较耗时的暴力方法,都pushdown到叶子节点(1138ms):

#pragma comment(linker,"/STACK:102400000,102400000")
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstdlib>
#include <stack>
#include <vector>
#include <set>
#include <map>
#define LL long long
#define mod 10007
#define inf 0x3f3f3f3f
#define N 2015
#define FILL(a,b) (memset(a,b,sizeof(a)))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
struct line
{
double l,r,h;
int d;
line(){}
line(double l,double r,double h,int d):l(l),r(r),h(h),d(d){}
bool operator<(const line &a)const
{
return h<a.h;
}
}s[N];
double sum[N<<],has[N];
int col[N<<];
void Pushup(int l,int r,int rt)
{
if(col[rt]>)sum[rt]=has[r+]-has[l];
else if(l==r)sum[rt]=;
else sum[rt]=sum[rt<<]+sum[rt<<|];
}
void Pushdown(int d,int l,int r,int rt)
{
if(l==r)
{
col[rt]+=d;
Pushup(l,r,rt);return;
}
int m=(l+r)>>;
Pushdown(d,lson);
Pushdown(d,rson);
Pushup(l,r,rt);
}
void update(int L,int R,int d,int l,int r,int rt)
{
if(L<=l&&r<=R)
{
Pushdown(d,l,r,rt);
return;
}
int m=(l+r)>>;
if(L<=m)update(L,R,d,lson);
if(m<R)update(L,R,d,rson);
Pushup(l,r,rt);
} int bin(double key,double a[],int n)
{
int l=,r=n-;
while(l<=r)
{
int m=(l+r)>>;
if(a[m]==key)return m;
if(a[m]>key)r=m-;
else l=m+;
}
return -;
}
int main()
{
int n,T;
double x1,y1,x2,y2;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
int k=;
for(int i=;i<n;i++)
{
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
has[k]=x1;
s[k++]=line(x1,x2,y1,);
has[k]=x2;
s[k++]=line(x1,x2,y2,-);
}
sort(s,s+k);
sort(has,has+k);
int m=;
for(int i=;i<k;i++)
if(has[i]!=has[i-])has[m++]=has[i];
double ans=;
for(int i=;i<k;i++)
{
int L=bin(s[i].l,has,m);
int R=bin(s[i].r,has,m)-;
update(L,R,s[i].d,,m-,);
ans+=sum[]*(s[i+].h-s[i].h);
}
printf("%.2lf\n",ans);
}
}