zoukankan      html  css  js  c++  java
  • HDU 6218 (线段树+set)

    HDU 6218 Bridge

    Problem :
    给一个2×n的矩阵,一开始矩阵所有相邻点之间有一条边。有其、个询问,每次给出两个相邻的点的坐标,将其中的边删除或者添加,问如此操作之后整张图的割边数量。
    , q<=2*10^5, 图始终保证联通。
    Solution :
    首先可以发现不能成为割边的边,一定被某个环所包含。因此只要维护每个环的大小即可。
    若某条横边在两行中均出现了两次,才有可能构成环。用set来维护所有连续的横边。再用线段树来维护所有竖边的位置。
    计算一条连续的横边产生的不能成为割边的数量,统计其中最左和最右的竖边以及竖边的数量就行了。

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int N = 2e5 + 8;
    const int INF = 1e9 + 7;
    
    #define endl "
    "
    #define y1 qqq
    struct node
    {
        int l, r;
        node(){}
        node(int l, int r):l(l),r(r){}
        bool operator < (const node &b) const
        {
            return l < b.l;
        }
    };
    multiset <node> S;
    int n, q, mtot, num;
    int cnt[N];
    class Segment_Tree
    {
    public:
        int tagmin[N << 2], tagmax[N << 2], tagsum[N << 2];
        void pushup(int rt)
        {
            tagmin[rt] = min(tagmin[rt << 1], tagmin[rt << 1 | 1]);
            tagmax[rt] = max(tagmax[rt << 1], tagmax[rt << 1 | 1]);
            tagsum[rt] = tagsum[rt << 1] + tagsum[rt << 1 | 1];
        }
        void build(int l, int r, int rt)
        {
            tagmin[rt] = INF; tagmax[rt] = 0; tagsum[rt] = 0;
            if (l == r)
            {
                tagmin[rt] = tagmax[rt] = l;
                tagsum[rt] = 1;
                return;
            }
            int m = l + r >> 1;
            build(l, m, rt << 1);
            build(m + 1, r, rt << 1 | 1);
            pushup(rt);
        }
        void update(int x, int op, int l, int r, int rt)
        {
            if (l == r)
            {
                if (op == 1)
                {
                    tagmin[rt] = tagmax[rt] = l; tagsum[rt] = 1;
                }
                else
                {
                    tagmin[rt] = INF; tagmax[rt] = 0; tagsum[rt] = 0;
                }
                return;
            }
            int m = l + r >> 1;
            if (x <= m) update(x, op, l, m, rt << 1);
            else update(x, op, m + 1, r, rt << 1 | 1);
            pushup(rt);
        }
        void querymax(int L, int R, int l, int r, int rt, int &ans)
        {
            if (L <= l && r <= R)
            {
                ans = max(ans, tagmax[rt]);
                return;
            }
            int m = l + r >> 1;
            if (L <= m) querymax(L, R, l, m, rt << 1, ans);
            if (m <  R) querymax(L, R, m + 1, r, rt << 1 | 1, ans);
        }
        void querymin(int L, int R, int l, int r, int rt, int &ans)
        {
            if (L <= l && r <= R)
            {
                ans = min(ans, tagmin[rt]);
                return;
            }
            int m = l + r >> 1;
            if (L <= m) querymin(L, R, l, m, rt << 1, ans);
            if (m <  R) querymin(L, R, m + 1, r, rt << 1 | 1, ans);
        }
        void querysum(int L, int R, int l, int r, int rt, int &ans)
        {
            if (L <= l && r <= R)
            {
                ans += tagsum[rt];
                return;
            }
            int m = l + r >> 1;
            if (L <= m) querysum(L, R, l, m, rt << 1, ans);
            if (m <  R) querysum(L, R, m + 1, r, rt << 1 | 1, ans);
        }
    }T;
    int calc(int l, int r)
    {
        int L = INF, R = -INF, sum = 0;
        T.querymin(l, r, 1, n, 1, L);
        T.querymax(l, r, 1, n, 1, R);
        T.querysum(l, r, 1, n, 1, sum);
        if (sum <= 1) return 0;
        return (R - L) * 2 + sum;
    }
    void init()
    {
        cin >> n >> q;
        T.build(1, n, 1);
        S.clear();
        for (int i = 1; i <= n; ++i) cnt[i] = 2;
        S.insert(node(1, n));
        S.insert(node(-1, -1));
        S.insert(node(n + 2, n + 2));
        mtot = 3 * n - 2;
        num = calc(1, n);
    }
    void work_row_add(int x)
    {
        auto l = S.upper_bound(node(x, x + 1)); l--;
        auto r = S.lower_bound(node(x, x + 1));
        cnt[x]++; mtot++;
        if (cnt[x] == 1)
        {
            cout << mtot - num << endl;
            return;
        }
        if (l->r == x && r->l == x + 1)
        {
            num -= calc(l->l, l->r);
            num -= calc(r->l, r->r);
            num += calc(l->l, r->r);
            S.insert(node(l->l, r->r));
            S.erase(l);
            S.erase(r);
        }
        else if (l->r == x && r->l != x + 1)
        {
            num -= calc(l->l, l->r);
            num += calc(l->l, x + 1);
            S.insert(node(l->l, x + 1));
            S.erase(l);
        }
        else if (l->r != x && r->l == x + 1)
        {
            num -= calc(r->l, r->r);
            num += calc(x, r->r);
            S.insert(node(x, r->r));
            S.erase(r);
        }
        else if (l->r != x && r->l != x + 1)
        {
            num += calc(x, x + 1);
            S.insert(node(x, x + 1));
        }
    }
    void work_row_del(int x)
    {
        auto p = S.upper_bound(node(x, x + 1)); p--;
        cnt[x]--; mtot--;
        if (cnt[x] == 0) return;
        if (p->l == x && p->r == x + 1)
        {
            num -= calc(x, x + 1);
            S.erase(p);
        }
        else if (p->l == x && p->r != x + 1)
        {
            num += calc(x+1,p->r);
            num -= calc(p->l,p->r);
            S.insert(node(x+1,p->r));
            S.erase(p);
        }
        else if (p->l != x && p->r == x + 1)
        {
            num += calc(p->l,x);
            num -= calc(p->l,p->r);
            S.insert(node(p->l,x));
            S.erase(p);
        }
        else if (p->l != x && p->r != x + 1)
        {
            num -= calc(p->l, p->r);
            num += calc(p->l, x);
            num += calc(x+1, p->r);
            S.insert(node(p->l, x));
            S.insert(node(x+1, p->r));
            S.erase(p);
        }
    }
    void work_col_add(int x)
    {
        auto p = S.upper_bound(node(x, x)); p--;
        mtot++;
        if (p->r >= x)
        {
            num -= calc(p->l, p->r);
            T.update(x, 1, 1, n, 1);
            num += calc(p->l, p->r);
        }
        else
        {
            T.update(x, 1, 1, n, 1);
        }
    }
    void work_col_del(int x)
    {
        auto p = S.upper_bound(node(x, x)); p--;
        mtot--;
        if (p->r >= x)
        {
            num -= calc(p->l, p->r);
            T.update(x, -1, 1, n, 1);
            num += calc(p->l, p->r);
        }
        else
        {
            T.update(x, -1, 1, n, 1);
        }
    }
    void solve()
    {
        for (; q; --q)
        {
            int op, x1, y1, x2, y2;
            cin >> op >> x1 >> y1 >> x2 >> y2;
    
            if (y1 > y2) swap(y1, y2);
            if (op == 1)
                if (x1 == x2) work_row_add(y1);
                else work_col_add(y1);
            else
                if (x1 == x2) work_row_del(y1);
                else work_col_del(y1);
            cout << mtot - num << endl;
        }
    }
    int main()
    {
        cin.sync_with_stdio(0);
        int T; cin >> T;
        for (int cas = 1; cas <= T; ++cas)
        {
            init();
            solve();
        }
    }
    
    
    
    
  • 相关阅读:
    sqlserver备份后无法还原的解决方法
    Silverlight如何与JS相互调用
    【转】体验 Silverlight 5 3D开发之环境搭配篇
    C#实现邮箱搬家功能(1):Pop3协议介绍
    【转】针对大数据量表的优化查询
    Centos7Docker安装Redis
    Centos7.*Consul安装配置
    Centos7Docker安装nacos
    Centos7Docker安装neo4j
    Spring框架根据传入参数动态的修改注解属性的值
  • 原文地址:https://www.cnblogs.com/rpSebastian/p/7834027.html
Copyright © 2011-2022 走看看