zoukankan      html  css  js  c++  java
  • Atlantis HDU

    //永远只考虑根节点的信息,说明在query时不会调用pushdown
    //所有操作均是成对出现,且先加后减
    // 
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <vector>
    using namespace std;
    const int N = 100010;
    int n;
    //存每一个操作 
    struct Segment
    {
        //区间长度 
        double x;
        //纵坐标 
        double y1, y2;
        //权值 
        int k;
        //按横坐标排序 
        bool operator< (const Segment &t)const
        {
            return x < t.x;
        }
    }seg[N * 2];
    struct Node
    {
        int l, r;
        //被覆盖的次数是多少 
        int cnt;
        //所有权值大于0的长度和是多少
        //不考虑祖先节点cnt的前提下(永远只向下看),cnt>0的区间总长 
        double len;
    }tr[N * 8];
    //离散化,y 
    vector<double> ys;
    //找离散化之后的值 
    int find(double y)
    {
        return lower_bound(ys.begin(), ys.end(), y) - ys.begin();
    }
    
    void pushup(int u)
    {
        if (tr[u].cnt) 
        //                    r+1才是下标    ,减完之后是长度 
            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 build(int u, int l, int r)
    {
        // cnt是0,len是0 
        tr[u] = {l, r, 0, 0};
        if (l != r)
        {
            int mid = l + r >> 1;
            build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
        }
    }
    
    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 (scanf("%d", &n), n)
        {
            ys.clear();
            for (int i = 0, j = 0; i < n; i ++ )
            {
                double x1, y1, x2, y2;
                scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);
                //对应的区间加1 
                seg[j ++ ] = {x1, y1, y2, 1};
                //对应的区间减1 
                seg[j ++ ] = {x2, y1, y2, -1};
                ys.push_back(y1), ys.push_back(y2);
            }
            //对应区间 
            //离散化 
            sort(ys.begin(), ys.end());
            ys.erase(unique(ys.begin(), ys.end()), ys.end());
            //从1号点开始,存的是区间,所以是0到ys.size()-2
            build(1, 0, ys.size() - 2);
            //排序 
            sort(seg, seg + n * 2);
            double res = 0;
            for (int i = 0; i < n * 2; i ++ )
            {
                //第一条线不能加 ,0的时候,还没点加进去 
                if (i > 0) 
                //            为1的长度    区间长度 
                    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
    ", T ++ );
            printf("Total explored area: %.2lf
    
    ", res);
        }
        return 0;
    }
  • 相关阅读:
    Running MYSQL 5.7 By Bash On Ubuntu On Windows:ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)
    MiniDao FreeMarker Cache 缓存问题
    Minidao FreeMarker 数组
    插入排序实例
    Binutils工具集中的一些比较常用的工具
    交叉编译工具简介
    TQ2440触摸屏
    对IIC总线时序的一点理解以及ACK和NACK(NAK)
    UART,SPI,IIC的一点理解
    linux中vi显示中文乱码的问题
  • 原文地址:https://www.cnblogs.com/QingyuYYYYY/p/12295590.html
Copyright © 2011-2022 走看看