线段树——线段树线段扫描(板子)

线段树——线段树线段扫描

#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;
}

发布了136 篇原创文章 · 获赞 218 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_34261446/article/details/104804933