zoukankan      html  css  js  c++  java
  • poj3277

    题意:给定每个矩形的高度以及底边在数轴上的起点和终点。各矩形间可能有重叠。问它们覆盖的总面积是多少。

    分析:线段树的题,开始以为不能用线段树,因为如果在已经插入了许多又瘦又高的楼的情况下,插入一个又矮又宽的楼横跨他们的话,就会对中间相交部分进行许多次修改复杂度远大于O(logn)。后来看了答案才知道,可以先把楼房按照高度从小到大排序,这样就不会出现这样的情况了。后来wa的原因是建树的范围比实际范围大了1个单位。另外,跨度横坐标需要离散化。

    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    
    #define MAX_INTERVAL 40005
    
    struct Building
    {
        int a, b, h;
    }building[MAX_INTERVAL];
    
    struct Node
    {
        int l, r;
        long long h;
        Node *pleft, *pright;
        long long value;
    }tree[MAX_INTERVAL *4];
    
    int n, discrete[MAX_INTERVAL *2], node_cnt, discrete_num;
    
    bool operator < (const Building &a, const Building &b)
    {
        return a.h < b.h;
    }
    
    bool ok(int index, int a)
    {
        return discrete[index] >= a;
    }
    
    int binary_search(int start, int end, int a)
    {
        int l = start;
        int r = end;
        while (l < r)
        {
            int mid = (l + r) / 2;
            if (ok(mid, a))
                r = mid;
            else
                l = mid + 1;
        }
        return l;
    }
    
    void input()
    {
        discrete_num =0;
        node_cnt =0;
        scanf("%d", &n);
        for (int i =0; i < n; i++)
        {
            scanf("%d%d%d", &building[i].a, &building[i].b, &building[i].h);
            discrete[discrete_num++] = building[i].a;
            discrete[discrete_num++] = building[i].b;
        }
    }
    
    void buildtree(Node *proot, int s, int e)
    {
        proot->l = s;
        proot->r = e;
        proot->h = 0;
        proot->value = 0;
        if (s == e)
        {
            proot->pleft = proot->pright = NULL;
            return;
        }
        node_cnt++;
        proot->pleft = tree + node_cnt;
        node_cnt++;
        proot->pright = tree + node_cnt;
        int mid = (s + e) / 2;
        buildtree(proot->pleft, s, mid);
        buildtree(proot->pright, mid + 1, e);
    }
    
    void add(Node *proot, int start, int end, long long h)
    {
        if (start > proot->r || end < proot->l)
            return;
        start = max(start, proot->l);
        end = min(end, proot->r);
        if (start == proot->l && end == proot->r)
        {
            proot->h = h;
            proot->value = h * (discrete[proot->r + 1] - discrete[proot->l]);
            return;
        }
        if (proot->h != -1 && proot->r != proot->l)
        {
            add(proot->pleft, proot->pleft->l, proot->pleft->r, proot->h);
            add(proot->pright, proot->pright->l, proot->pright->r, proot->h);
            proot->h = -1;
        }
        add(proot->pleft, start, end, h);
        add(proot->pright, start, end, h);
        proot->value = proot->pleft->value + proot->pright->value;
    }
    
    void discretization(int discrete[], int &discrete_num)
    {
        sort(discrete, discrete + discrete_num);
        discrete_num = unique(discrete, discrete + discrete_num) - discrete;
    }
    
    int main()
    {
        input();
        sort(building, building + n);
        discretization(discrete, discrete_num);
        buildtree(tree, 0, discrete_num - 2);
        for (int i =0; i < n; i++)
        {
            int l = binary_search(0, discrete_num - 1, building[i].a);
            int r = binary_search(0, discrete_num - 1, building[i].b);
            add(tree, l, r - 1, building[i].h);
        }
        printf("%lld\n", tree->value);
        return 0;
    }
    View Code
  • 相关阅读:
    C#获取类以及类下的方法(用于Asp.Net MVC)
    ES6学习笔记
    在nuget上发布自己的程序集教程
    C#创建IIS站点及相应的应用程序池,支持IIS6.0+Windows Server 2003. 使用Builder设计模式
    ASP.Net Mvc实现自定义User Identity用户身份识别系统(2)
    ASP.Net Mvc实现自定义User Identity用户身份识别系统(1)
    C#实现.ini文件读写操作
    C#实现注册表 LocalMachine 目录下CURD工具类
    博客园打赏功能(未申请下js权限使用二维码打赏功能)
    WebServeice 动态代理类
  • 原文地址:https://www.cnblogs.com/rainydays/p/1965321.html
Copyright © 2011-2022 走看看