线段树——线段树线段扫描
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn = 1e5;
struct Line
{
double l, r, h;
int d;
bool operator < (const Line & a) const
{
return h < a.h;
}
} line[maxn];
double X[maxn]; //用于离散化的
int mark[maxn << 2]; //用与统计 下行边 与 上行边 之差
double sum[maxn << 2]; //用于统计当前某个区间段的长度
int Search(double x, double X[], int Len)
{
int l = 0, r = Len - 1;
while(l <= r)
{
int m = (l + r) >> 1;
if(X[m] == x)
return m;
else if(X[m] > x) r = m - 1;
else l = m + 1;
}
return -1;
}
void Push_up(int pos, int L, int R)
{
if(mark[pos]) sum[pos] = X[R + 1] - X[L];
else if(L == R) sum[pos] = 0; //叶子节点则底边长度为0 (区间的线段长度为0)
else sum[pos] = sum[pos << 1] + sum[pos << 1 | 1];
}
void Update(int pos, int L, int R, int s, int e, int d)
{
if(s <= L && R <= e)
{
mark[pos] += d;
Push_up(pos, L, R);
return;
}
int m = (L + R) >> 1;
if(s <= m) Update(pos << 1, L, m, s, e, d);
if(e > m) Update(pos << 1 | 1, m + 1, R, s, e, d);
Push_up(pos, L, R);
}
int main()
{
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
freopen("A.txt","r",stdin);
int n;
while(cin >> n && n)
{
int pos = 0;
double x1, x2, y1, y2;
for(int i = 1; i <= n; i ++)
{
cin >> x1 >> y1 >> x2 >> y2;
X[pos] = x1;
line[pos ++] = (Line){ x1, x2, y1, 1};
X[pos] = x2;
line[pos ++] = (Line){ x1, x2, y2, -1};
}
//坐标排序
sort(X, X + pos);
sort(line, line + pos);
//坐标离散化(去重复端点、缩小占用的区间)
int pla = 1;
for(int i = 1; i < pos ; i ++)
{
if(X[i] != X[i - 1])
X[pla ++] = X[i];
}
double ans = 0;
for(int i = 0; i < pos; i ++)
{
int s = Search(line[i].l, X, pla);
int e = Search(line[i].r, X, pla) - 1;
Update(1, 0, pla - 1, s, e, line[i].d);
ans += sum[1] * (line[i + 1].h - line[i].h);
}
cout << ans << endl;
}
return 0;
}