扫描线板子题 没啥好说的
输入矩形两点 然后求覆盖两次的面积
(sum为覆盖面积,sums为覆盖两次的面积)
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<map>
#include<string>
#include<string.h>
using namespace std;
const int maxn = 10000+10;
int mark[maxn<<2];
double sum[maxn<<2];
double sums[maxn<<2];
double hashs[maxn];
struct seg{
double l,r,h;
int d;
seg(){
}
seg(double x1,double x2,double H, int c):l(x1),r(x2),h(H),d(c){}
bool operator <(const seg &a)const{
return h<a.h;
}
}s[maxn];
void upfather(int n,int l,int r){
if(mark[n])sum[n] = hashs[r+1]-hashs[l];
else if(l==r)sum[n]= 0;
else{
sum[n] = sum[n<<1]+sum[n<<1|1];
}
if(mark[n]>1){
sums[n] = hashs[r+1]-hashs[l];
}
else if(l== r)sums[n] = 0;
else if(mark[n]==1){
sums[n] = sum[n<<1]+sum[n<<1|1];
}
else sums[n] = sums[n<<1]+sums[n<<1|1];
}
void update(int L,int R, int d,int n,int left, int right){
if(left>=L&&right<=R){
mark[n]+=d;
upfather(n,left,right);
return;
}
int mid = (left+right)>>1;
if(L<=mid){
update(L,R,d,n<<1,left,mid);
}
if(R>mid){
update(L,R,d,n<<1|1,mid+1,right);
}
upfather(n,left,right);
return;
}
int main(){
int q,num = 0;
double x1,x2,y1,y2;
int t;
cin>>t;
while(t--){
cin>>q;
{
memset(sum,0,sizeof(sum));
memset(sums,0,sizeof(sums));
memset(mark,0,sizeof(mark));
int n = 0;
int m = 0;
for(int i = 1;i<=q;++i){
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
hashs[++n] = x1;
hashs[++n] = x2;
s[++m] = seg(x1,x2,y1,1);
s[++m] = seg(x1,x2,y2,-1);
}
//cout<<k<<endl;
sort(hashs+1,hashs+1+n);
sort(s+1,s+m+1);
int k = unique(hashs+1,hashs+n+1) - hashs-1;
//cout<<"m"<<m<<endl;
double ans = 0;
for(int i = 1;i<=m;++i){
int L = lower_bound(hashs+1,hashs+k+1,s[i].l)-hashs;
int R = lower_bound(hashs+1,hashs+k+1,s[i].r)-hashs-1;
update(L,R,s[i].d,1,1,k);
ans+=sums[1]*(s[i+1].h-s[i].h);
}
printf("%.2lf\n",ans);
}
}
}
/*
2
0 0 4 4
1 1 3 3
*/