大佬的博客
看了好几天,感觉自己看懂了。
https://blog.csdn.net/riba2534/article/details/76851233这个大佬内部有图,可以手动纸上跟着画一下加深理解
扫描线可以水平扫,也可以垂直扫,这里我说一下垂直扫吧。
题目给出的坐标为浮点数,那么我们将所有的y坐标排序离散化后,假设共有m个不同的坐标值,设为val[1~m]。
那么这m个不同的y值就可以将一条垂直x轴的直线划分为m-1段吧(超出最大的y,与小于最小的y的地方不算),
那么为这m-1个线段标号分别为1~m-1,线段树维护的就是这m-1根线段被覆盖了多少次。
就比如节点[1,1]就表示的是线段1,长度为val[2]-val[1]。[2,5]就表示的是从2~5包含的所有线段,长度为val[6]-val[2]。
将每个矩形拆成两个四元组 (x1,y1,y2,1) (x2,y1,y2,-1) 按照x从小到大排序逐次将2*n-1条加入线段树(不加入最后一条)
线段树中的每个节点都表示不同的含义,不同于普通的线段树需要将子树的信息更新到叶子节点。
不下传标记
一道裸题:https://www.acwing.com/problem/content/249/
#include
using namespace std;
const int maxn=209;
double y[maxn];
int cnt[maxn<<2|1];
double len[maxn<<2|1];
int m;
struct Node{
double y1,y2,h;
int v;
bool operator <(const Node& x)const{
return h=L&&r<=R){
cnt[k]+=v;
pushup(l,r,k);
return ;
}
int mid=(l+r)>>1;
if(L<=mid) updata(L,R,l,mid,k<<1,v);
if(R>mid) updata(L,R,mid+1,r,k<<1|1,v);
pushup(l,r,k);
}
void prin(){
for(int i=1;i<=20;++i) cout<
这位大佬有讲面积交:https://www.cnblogs.com/lxjshuju/p/7040186.html
#include
using namespace std;
typedef long long ll;
const int maxn=2009;
double y[maxn];
int m;
void quchong(int n){
sort(y+1,y+1+n);
m=unique(y+1,y+1+n)-(y+1);
}
int getid(double x){
return lower_bound(y+1,y+1+m,x)-(y+1)+1;
}
struct Node{
double h,y1,y2;
int v;
bool operator <(const Node& x)const{
return h=2) len2[k]=y[r+1]-y[l];
else if(l==r) len2[k]=0;
else if(cnt[k]==1) len2[k]=len1[k<<1]+len1[k<<1|1];
else len2[k]=len2[k<<1]+len2[k<<1|1];
}
void updata(int L,int R,int l,int r,int k,int v){
if(l>=L&&r<=R){
cnt[k]+=v;
pushup(l,r,k);
return ;
}
int mid=(l+r)>>1;
if(L<=mid) updata(L,R,l,mid,k<<1,v);
if(R>mid) updata(L,R,mid+1,r,k<<1|1,v);
pushup(l,r,k);
}
int main(){
int t;
scanf("%d",&t);
int n;
double x1,x2,y1,y2;
while(t--){
build();
scanf("%d",&n);
for(int i=1;i<=n;++i){
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
int k=(i<<1);
a[k-1].h=x1,a[k-1].y1=y1,a[k-1].y2=y2,a[k-1].v=1;
a[k].h=x2,a[k].y1=y1,a[k].y2=y2,a[k].v=-1;
y[k-1]=y1,y[k]=y2;
}
double res=0;
n<<=1;
sort(a+1,a+1+n);
quchong(n);
for(int i=1;i