zoukankan      html  css  js  c++  java
  • HDU2461 Rectangles 线段树,矩形面积并

    首先申明此方法POJ超时,HDU压线过,优化版见http://www.cnblogs.com/Lyush/archive/2012/07/28/2613516.html

    线段树的写法与上面链接中的离散化版本的想法是相近的,只不过这里仅仅是通过线段树来保留某一x区域的多个矩形的面积并。

    代码如下:

    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <map>
    #include <algorithm>
    using namespace std;
    
    int N, M, Q, cnt;
    
    map<int,int>mp;
    
    struct Rectangle
    {
        int x1, y1, x2, y2;
    }e[25];
    
    struct High
    {
        int y;
        bool operator < (High temp) const
        {
            return y < temp.y;
        }
        bool operator == (High temp) const
        {
            return y == temp.y;
        }
    }H[50];
    
    struct xLine
    {
        int x, y1, y2, sign;
        bool operator < (xLine temp) const
        {
            return x < temp.x;
        }
    }Line[50];
    
    struct Node
    {
        int l, r, lazy;
    }s[200];
    
    void build(int p, int l, int r)
    {
        s[p].l = l, s[p].r = r;
        s[p].lazy = 0;  // 初始化为被覆盖了0次
        if (l != r) {
            int mid = (l + r) >> 1;
            build(p<<1, l, mid);
            build(p<<1|1, mid+1, r);
        }
    }
    
    void push_up(int p)
    {
        
    }
    
    void push_down(int p)
    { 
        if (s[p].lazy != 0) {
            s[p<<1].lazy += s[p].lazy;
            s[p<<1|1].lazy += s[p].lazy;
            s[p].lazy = 0;
        }
    }
    
    void modify(int p, int l, int r, int val)
    {
        if (l == s[p].l && r == s[p].r) {
            s[p].lazy += val;
        }
        else {
            int mid = (s[p].l + s[p].r) >> 1;
            push_down(p);
            if (r <= mid) {
                modify(p<<1, l, r, val);
            }
            else if (l > mid) {
                modify(p<<1|1, l, r, val);
            }
            else {
                modify(p<<1, l, mid, val);
                modify(p<<1|1, mid+1, r, val);
            }
            push_up(p);
        }
    }
    
    int query(int p)
    {
        if (s[p].l == s[p].r) {
            return (bool)(s[p].lazy) * (H[s[p].r].y - H[s[p].l-1].y);
        }
        else {
            push_down(p);
            return query(p<<1) + query(p<<1|1);
        }
    }
    
    int main()
    {
        int c, sum, ca = 0;
        while (scanf("%d %d", &N, &M), N|M) {
            for (int i = 1; i <= N; ++i) {
                scanf("%d %d %d %d", &e[i].x1, &e[i].y1, &e[i].x2, &e[i].y2); 
            }
            printf("Case %d:\n", ++ca);
            for (int t = 1; t <= M; ++t) {
                sum = 0; 
                mp.clear();
                scanf("%d", &Q);
                for (int j = 1, k = 0; j <= Q; ++j, k += 2) {
                    scanf("%d", &c);
                    Line[k].x = e[c].x1, Line[k+1].x = e[c].x2;
                    Line[k].sign = 1, Line[k+1].sign = -1;
                    // 定义 1为入边,-1为出边
                    Line[k].y1 = e[c].y1, Line[k].y2 = e[c].y2;
                    Line[k+1].y1 = e[c].y1, Line[k+1].y2 = e[c].y2;
                    H[k].y = e[c].y1, H[k+1].y = e[c].y2;
                }
                sort(H, H+2*Q); // 对y轴坐标进行离散话
                cnt = unique(H, H+2*Q) - H; // 去重
                for (int i = 0; i < cnt; ++i) {
                    mp[H[i].y] = i;
                }
                sort(Line, Line+2*Q);
                for (int i = 0; i < 2*Q; ++i) {
                    Line[i].y1 = mp[Line[i].y1];
                    Line[i].y2 = mp[Line[i].y2];
                    // 将y坐标进行离散化
                }
                build(1, 0, cnt-1);  // 建立一个空的树来表示整个纵坐标的覆盖情况
                modify(1, Line[0].y1+1, Line[0].y2, Line[0].sign); 
                for (int i = 1; i < (Q << 1); ++i) { // 遍历每一个
                    sum += query(1) * (Line[i].x - Line[i-1].x); 
                    modify(1, Line[i].y1+1, Line[i].y2, Line[i].sign); 
                }
                printf("Query %d: %d\n", t, sum);
            }
            puts("");
        }
        return 0;
    }
  • 相关阅读:
    BZOJ2809: [Apio2012]dispatching
    BZOJ1455: 罗马游戏
    可并堆试水--BZOJ1367: [Baltic2004]sequence
    可并堆模板
    Codeforces870F. Paths
    Codeforces913F. Strongly Connected Tournament
    一练Splay之维修数列第一次
    Codeforces913E. Logical Expression
    Codeforces700C. Break Up
    可持久化KMP
  • 原文地址:https://www.cnblogs.com/Lyush/p/2614970.html
Copyright © 2011-2022 走看看