扫描线
题意
多个矩阵求交集,线段树的特殊操作,非常特殊的情况,一堆证明之后,就没有pushdown操作。
没有pushdown操作,也没有query操作,直接tr[1].len.
亚特兰蒂斯
由于点可能有小数,先l、离散化为整数,这里的线段树存的是一个区间:【L,R),左闭右开的区间。 换句话:线段树存的是第几个小区间,那么操作(l,r)的话,对线段树操作:l–r-1就够了,(存的不是点,是小区间,小区间比点的数量少1)
另外,也不需要query()函数,之间调用tr[1].len,返回线段长度
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>
#include<queue>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define mst(s,_s) memset(s, _s, sizeof(s))
const double PI = acos(-1.0);
const double eps = 1e-6;
const int INF = 0x3f3f3f3f;
const int N = 1e6+100;
int T,n,m;
struct seg1{
double x,y1,y2;
int k;
bool operator<(const seg1 & t)const{
return x<t.x;
}
}seg[N];
struct node{
int l,r,cnt;
double len;
}tr[N];
vector<double>ys;
double find(double y)
{
return lower_bound(ys.begin(),ys.end(),y) - ys.begin();
}
void build(int u,int l,int r)
{
if(l==r) tr[u]={l,r,0,0.0};
else{
tr[u]={l,r,0,0.0};
int mid=l+r>>1;
build(u<<1,l,mid),build(u<<1|1,mid+1,r);
}
}
void pushup(int u)
{
if(tr[u].cnt)
{
tr[u].len=(ys[tr[u].r+1]-ys[tr[u].l]);
}
else if(tr[u].l!=tr[u].r)
{
tr[u].len= tr[u<<1].len+tr[u<<1|1].len;
}
else tr[u].len=0;
}
void modify(int u,int l,int r,int k)
{
if(tr[u].l>=l && tr[u].r<=r)
{
tr[u].cnt+=k;
pushup(u);
}
else{
int mid=tr[u].l+tr[u].r>>1;
if(l<=mid) modify(u<<1,l,r,k);
if(r>mid) modify(u<<1|1,l,r,k);
pushup(u);
}
}
int main() {
int T=1;
while(cin>>n)
{
if(n==0) break;
ys.clear();
for(int i=0,j=0;i<n;i++)
{
double x1,y1,x2,y2;
cin>>x1>>y1>>x2>>y2;
ys.push_back(y1);
ys.push_back(y2);
seg[j++]={x1,y1,y2,1};
seg[j++]={x2,y1,y2,-1};
}
sort(seg,seg+n*2);
sort(ys.begin(),ys.end());
ys.erase(unique(ys.begin(),ys.end()),ys.end());
build(1,0,ys.size()-2);
double res=0.0;
for(int i=0;i<2*n;i++)
{
if(i>0) res+=(tr[1].len * (seg[i].x-seg[i-1].x));
modify(1,find(seg[i].y1),find(seg[i].y2) -1 ,seg[i].k);
}
printf("Test case #%d\n", T ++ );
printf("Total explored area: %.2lf\n\n", res);
}
return 0;
}
普通版本扫描线
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>
#include<queue>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define mst(s,_s) memset(s, _s, sizeof(s))
const double PI = acos(-1.0);
const double eps = 1e-6;
const int INF = 0x3f3f3f3f;
const int N = 1e6+100;
int T,n,m;
struct seg1{
int x,y1,y2;
int k;
bool operator<(const seg1 & t)const{
return x<t.x;
}
}seg[N];
struct node{
int l,r,cnt;
int len;
}tr[N];
void build(int u,int l,int r)
{
if(l==r) tr[u]={l,r,0,0};
else{
tr[u]={l,r,0,0};
int mid=l+r>>1;
build(u<<1,l,mid);
build(u<<1|1,mid+1,r);
}
}
void pushup(int u)
{
if(tr[u].cnt) tr[u].len = tr[u].r+1-tr[u].l;
else if(tr[u].l!=tr[u].r) tr[u].len = tr[u<<1].len+tr[u<<1|1].len;
else{
tr[u].len=0;
}
}
void motify(int u,int l,int r,int k)
{
if(l<=tr[u].l && tr[u].r<=r)
{
tr[u].cnt+=k;
pushup(u);
}
else{
int mid=tr[u].l+tr[u].r>>1;
if(l<=mid) motify(u<<1,l,r,k);
if(r>mid) motify(u<<1|1,l,r,k);
pushup(u);
}
}
int main() {
cin>>n;
int m = 0;
for(int i=0,j=0;i<n;i++)
{
int x1,x2,y1,y2;
cin>>x1>>y1>>x2>>y2;
seg[j++]={x1,y1,y2,1};
seg[j++]={x2,y1,y2,-1};
}
//sort(seg, seg + m);
sort(seg,seg+2*n);
build(1,0,10000);
ll res=0;
for(int i=0;i<2*n;i++)
{
if(i>0) res+=tr[1].len * (seg[i].x - seg[i-1].x);
motify(1,seg[i].y1,seg[i].y2-1,seg[i].k);
}
cout<<res<<endl;
return 0;
}