给出若干个矩形的坐标,矩形之间存在重叠。问所有矩形覆盖的总面积是多少。
对于每个矩形抽象成两条线,每一个线记录:x轴坐标,上端点坐标,下端点坐标。另外对于每一条线记录一个属性val,如果这个线是矩形左边的线,那么val值为1,右边为-1。然后把这些线段按x轴坐标从左到右排序。
离散y轴,每条线段就是相当于覆盖一定的区间。从左到右扫每条线段,利用线段树维护当前被覆盖的长度sum,sum乘上线段之间的距离就是这一部分所要求的的面积。
因为任何一段区间必定是先+1后-1,所以不会存在负数。这个线段树的节点也可以理解成线段,num记录的就是这条线段覆盖了几次。
#include
using namespace std;
typedef long long ll;
const int N=1e2+7;
struct Edge{
double x;
int up,dw;
int val;
bool operator<(const Edge a)const{
return x>1;
if(L<=m) update(L,R,l,m,rt<<1,val);
if(m
给出若干个矩形,求出至少被覆盖两次的面积。
和上一题思路类似,同样是扫描线离散线段树的处理。
只不过这题线段树处理的要有些不一样,因为要考虑覆盖的次数,我在上面一题的基础上写了pushdown操作来维护。
注意这几点:
#include
using namespace std;
typedef long long ll;
const int N=1e3+7;
struct Edge{
double x;
int up,dw;
int val;
bool operator<(const Edge a)const{
return x>1;
num[rt<<1]+=lz[rt];
if(num[rt<<1]>1) sum[rt<<1]=y[m+1]-y[l];
else sum[rt]=0;
num[rt<<1|1]+=lz[rt];
if(num[rt<<1|1]>1) sum[rt<<1|1]=y[r+1]-y[m+1];
else sum[rt]=0;
lz[rt<<1]+=lz[rt];
lz[rt<<1|1]+=lz[rt];
lz[rt]=0;
}
}
void pu(int rt){
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void update(int L,int R,int l,int r,int rt,int val,bool flag){
if(L<=l&&r<=R){
if(flag){
num[rt]+=val;
lz[rt]+=val;
}
flag=false;
if(num[rt]>1){
sum[rt]=y[r+1]-y[l];
return;
}
}
if(l==r){
sum[rt]=0;
return;
}
pd(l,r,rt);
int m=l+r>>1;
if(L<=m) update(L,R,l,m,rt<<1,val,flag);
if(m
给出一些矩阵,求出所有矩形覆盖形成的图形的周长。
与面积并类似的解法。
当然只维护一个,横竖扫两遍也可以。
注意扫描线的排序如果产生了重合,那么插入的优先级要高,不然sum可能会多算。
#include
#include
#include
using namespace std;
const int N=5e3+7;
int lx[N],ly[N],rx[N],ry[N];
int y[N*2];
struct Edge{
int le,ri,x;
int val;
Edge(int le=0,int ri=0,int x=0,int val=0):le(le),ri(ri),x(x),val(val){}
bool operator<(const Edge a)const{
if(x==a.x) return val>a.val;
return x>1;
build(l,m,rt<<1);
build(m+1,r,rt<<1|1);
}
void pu(int l,int r,int rt){
if(a[rt].num){
a[rt].sum=y[r+1]-y[l];
a[rt].cnt=1;
a[rt].ll=a[rt].rr=true;
}
else if(l==r){
a[rt].sum=a[rt].cnt=0;
a[rt].ll=a[rt].rr=false;
}
else{
a[rt].sum=a[rt<<1].sum+a[rt<<1|1].sum;
a[rt].cnt=a[rt<<1].cnt+a[rt<<1|1].cnt;
if(a[rt<<1].rr&&a[rt<<1|1].ll) a[rt].cnt--;
a[rt].ll=a[rt<<1].ll;a[rt].rr=a[rt<<1|1].rr;
}
}
void update(int L,int R,int l,int r,int rt,int val){
if(L<=l&&r<=R){
a[rt].num+=val;
pu(l,r,rt);
return;
}
int m=l+r>>1;
if(L<=m) update(L,R,l,m,rt<<1,val);
if(m