• bzoj 1018 堵塞的交通traffic 线段树维护区间连续性


    bzoj 1018 堵塞的交通traffic

    Description

    有一天,由于某种穿越现象作用,你来到了传说中的小人国

    小人国的布局非常奇特,整个国家的交通系统可以被看成是一个(2)(C)列的矩形网格,网格上的每个点代表一个城市,相邻的城市之间有一条道路,所以总共有2(C)个城市和(3C-2)条道路。

    小人国的交通状况非常槽糕。

    有的时候由于交通堵塞,两座城市之间的道路会变得不连通,直到拥堵解决,道路才会恢复畅通。

    初来咋到的你决心毛遂自荐到交通部某份差事,部长听说你来自一个科技高度发达的世界,喜出望外地要求你编写一个查询应答系统,以挽救已经病入膏肓的小人国交通系统。

    小人国的交通部将提供一些交通信息给你,你的任务是根据当前的交通情况回答查询的问题。

    交通信息可以分为以下几种格式:

    Close r1 c1 r2 c2:相邻的两座城市(r1,c1)和(r2,c2)之间的道路被堵塞了;

    Open r1 c1 r2 c2:相邻的两座城市(r1,c1)和(r2,c2)之间的道路被疏通了;

    Ask r1 c1 r2 c2:询问城市(r1,c1)和(r2,c2)是否连通。

    如果存在一条路径使得这两条城市连通,则返回Y,否则返回N;

    Input

    第一行只有一个整数(C),表示网格的列数。

    接下来若干行,每行为一条交通信息,以单独的一行“Exit”作为结束。

    我们假设在一开始所有的道路都是堵塞的。

    我们保证 C小于等于(100000),信息条数小于等于(100000)

    Output

    对于每个查询,输出一个“Y”或“N”。

    Sample Input

    2
    Open 1 1 1 2
    Open 1 2 2 2
    Ask 1 1 2 2
    Ask 2 1 2 2
    Exit
    

    Sample Output

    Y
    N
    

    题解

    只有两行,我们可以维护列区间([l, r])矩形的联通性

    记录区间矩形

    (左上,左下),(右上,右下),(左上,右上),(左下,右下),(左上,右下),(左下,右上)点对是否联通

    合并两个相邻的区间时,矩形这些条件也很好维护

    对于最底层的矩形也就是区间([l, l + 1])

    我们单独记录每个小矩形内的四条边, 来维护区间([l, l + 1])

    这样就可以维护整棵线段树了

    问题是询问(假定(y_1 <= y_2)

    单独把包含询问的两个点的矩形拿出来并不能解决问题,

    因为一个点(除了端点)都属于两个矩形,左边的点,可以借助其存在的坐矩形达到右边的点,右边的点同理

    图是网图, 坐标反了, 凑合看吧

    对于竖线((y_1 = y_2)),提取出来([1, y_1], [y_1, n + 1]) 来获得答案

    对于其他,提取出([1, y_1],[y_1, y_2], [y_2, n + 1]) 来获得答案

    具体怎么合并区间和获得答案看看代码自己画画图,也就懂了

    struct BIT {
        struct node {
            //l, r, u, d, p, q
            //(左上,左下),(右上,右下),(左上,右上),(左下,右下),(左上,右下),(左下,右上)点对是否联通
            bool l, r, u, d, p, q;
        } tr[N << 2];
        bool edge[N][4]; //小矩形内部上下左右四条表是否存在
        node unit(const node&a, const node& b) {
            node c;
            c.l = a.l | (a.u & a.d & b.l);
            c.r = b.r | (b.u & b.d &a.r);
            c.u = (a.u & b.u) | (a.p & b.q);
            c.d = (a.d & b.d) | (a.q & b.p);
            c.p = (a.u & b.p) | (a.p & b.d);
            c.q = (a.d & b.q) | (a.q & b.u);
            return c;
        }
        void check(int p, int id) {
            tr[p].u = edge[id][0];
            tr[p].d = edge[id][1];
            tr[p].l = edge[id][2];
            tr[p].r = edge[id][3];
            tr[p].p = tr[p].q = 0;
            tr[p].u |= tr[p].l & tr[p].r & tr[p].d;
            tr[p].d |= tr[p].l & tr[p].r & tr[p].u;
            tr[p].l |= tr[p].u & tr[p].r & tr[p].d;
            tr[p].r |= tr[p].l & tr[p].u & tr[p].d;
            tr[p].p = (tr[p].u & tr[p].r) | (tr[p].l & tr[p].d);
            tr[p].q = (tr[p].d & tr[p].r) | (tr[p].l & tr[p].u);
        }
        //默认道路全部关闭,不需要build
        //坐标(x1, y1)在(x2, y2)的左边(y1 <= y2)
        void change(int p, int l, int r, int x1, int y1, int x2, int y2, bool open) {
            if (l + 1 == r && y1 >= l && y2 <= r) {
                if (y1 ^ y2)
                    if (x1 == 1)
                        edge[l][0] = open;
                    else
                        edge[l][1] = open;
                else if (x1 ^ x2)
                    if (y1 == l)
                        edge[l][2] = open;
                    else
                        edge[l][3] = open;
                check(p, l);
                return;
            }
            int mid = l + r >> 1;
            if (mid >= y2)
                change(p << 1, l, mid, x1, y1, x2, y2, open);
            if (mid <= y1)
                change(p << 1 | 1, mid, r, x1, y1, x2, y2, open);
            tr[p] = unit(tr[p << 1], tr[p << 1 | 1]);
        }
        //坐标(x1, y1)在(x2, y2)的左边(y1 <= y2)
        node ask(int p, int l, int r, int y1, int y2) {
            if (y1 == y2)
                return node();
            if (y1 <= l && r <= y2)
                return tr[p];
            int mid = l + r >> 1;
            if (mid >= y2)
                return ask(p << 1, l, mid, y1, y2);
            if (mid <= y1)
                return ask(p << 1 | 1, mid, r, y1, y2);
            return unit(ask(p << 1, l, mid, y1, y2), ask(p << 1 | 1, mid, r, y1, y2));
        }
        bool aask(int n, int x1, int y1, int x2, int y2) {
            if (y1 ^ y2) {
                node a = ask(1, 1, n, 1, y1);
                node b = ask(1, 1, n, y1, y2);
                node c = ask(1, 1, n, y2, n);
    
                if (x1 == x2)
                    if (x1 == 1)
                        return b.u | ((a.r | b.l) & b.d & (c.l | b.r)); 
                    else
                        return b.d | ((a.r | b.l) & b.u & (c.l | b.r));
                else
                    if (x1 == 1)
                        return b.p | (a.r & b.d) | (c.l & b.u);
                    else
                        return b.q | (c.l & b.d) | (a.r & b.u);
            } else {
                if (x1 == x2)
                    return 1;
                return ask(1, 1, n, 1, y1).r | ask(1, 1, n, y1, n).l;
            }
            return 0;
        }
    } bit;
    
    int main() {
        ios::sync_with_stdio(0);
        cin.tie(0), cout.tie(0);
    
        int n;
        cin >> n;
        ++n;
    
        string s;
        for (cin >> s; s[0] ^ 'E'; cin >> s) {
            int x1, y1, x2, y2;
            cin >> x1 >> y1 >> x2 >> y2;
            if (y1 > y2)
                swap(x1, x2), swap(y1, y2);
            if (s[0] == 'O') 
                bit.change(1, 1, n, x1, y1, x2, y2, 1);
            else if (s[0] == 'C')
                bit.change(1, 1, n, x1, y1, x2, y2, 0);
            else
                cout << (bit.aask(n, x1, y1, x2, y2) ? 'Y' : 'N') << '
    ';
        }
        return 0;
    }
    
  • 相关阅读:
    easyUI之tree
    MSSQL索引优化
    MongoDB学习笔记(一) MongoDB介绍及安装
    项目经理必备的11种人际关系技能
    http协议详细介绍
    ERP存储过程
    UVA1339 UVALive3213 POJ2159 ZOJ2658 Ancient Cipher【密码】
    UVA1588 UVALive3712 POJ3158 Kickdown
    UVA1588 UVALive3712 POJ3158 Kickdown
    UVA10340 POJ1936 ZOJ1970 All in All【字符串匹配】
  • 原文地址:https://www.cnblogs.com/2aptx4869/p/15020755.html
Copyright © 2020-2023  润新知