zoukankan      html  css  js  c++  java
  • Luogu P4169 [Violet]天使玩偶/SJY摆棋子

    学了不清真的(sort)写法(CDQ)分治的蒟蒻在本题的数据面前瑟瑟发抖。。。。。

    实际上就是一个常规的(CDQ)模型,但是关键难点有两个:

    • 需要进行四次(CDQ)。你可以选择把图旋转四次,也可以像我一样写四次(solve)从而获得(7kb)的代码

    • 用树状数组维护区间最大值的时候(y)可能为(0),会死循环,要(+1)处理。

    • 不要使用不清真的(sort)写法!

    (Code:)

    // luogu-judger-enable-o2
    #include <bits/stdc++.h>
    using namespace std;
    
    const int N = 300000 + 5;
    const int M = 600000 + 5;
    const int K = 1000000 + 100;
    const int MaxK = 1000000 + 50;
    const int INF = 0x3f3f3f3f;
    #define lowbit(x) (x & -x)
    
    int n, m, tot, qry[N], qryid;
    
    struct Node {
        int x, y, w, id, ans, opt; // 1 / 2 : 操作 / 查询 
    
        void out () {
            if (opt == 1) {
                cout << "{Opt : (" << x << ", " << y << "), w = " << w << "}"; 
            } else {
                cout << "{Qry : (" << x << ", " << y << "), w = " << w << " id = " << id << " ans = " << ans << "}"; 
            }
        }
    }arr[M], tmp[M];
    
    bool cmp1 (Node lhs, Node rhs) {return lhs.x == rhs.x ? lhs.y < rhs.y : lhs.x < rhs.x;} // x1 <= x2, y1 <= y2
    bool cmp2 (Node lhs, Node rhs) {return lhs.x == rhs.x ? lhs.y > rhs.y : lhs.x < rhs.x;} // x1 <= x2, y1 >= y2
    bool cmp3 (Node lhs, Node rhs) {return lhs.x == rhs.x ? lhs.y < rhs.y : lhs.x > rhs.x;} // x1 >= x2, y1 <= y2
    bool cmp4 (Node lhs, Node rhs) {return lhs.x == rhs.x ? lhs.y > rhs.y : lhs.x > rhs.x;} // x1 >= x2, y1 >= y2
    
    int tree[K];
    
    void add_val (int pos, int val) {
        while (pos < K) {
            tree[pos] = max (tree[pos], val);
            pos += lowbit (pos);
        }
    }
    
    int get_val (int pos) {
        int ret = -INF;
        while (pos != 0) {
            ret = max (ret, tree[pos]);
            pos -= lowbit (pos);
        }
        return ret;
    }
    
    void clear (int pos) {
        while (pos < K) {
            tree[pos] = -INF;
            pos += lowbit (pos);
        }
    }
    
    Node _loc[M];
    
    void cdq1 (int l, int r) {
        if (r == l + 1) return;
        int mid = (l + r) >> 1;
        cdq1 (l, mid), cdq1 (mid, r);
    //	sort (tmp + l, tmp + mid, cmp1);
    //	sort (tmp + mid, tmp + r, cmp1);
        int pl = l, pr = mid, k = l;
        while (pr < r) {
            while (pl < mid && tmp[pl].x <= tmp[pr].x) {
                if (tmp[pl].opt == 1) {
                    add_val (tmp[pl].y + 1, tmp[pl].w);
                }
                _loc[k++] = tmp[pl++];
            }
            if (tmp[pr].opt == 2) {
                tmp[pr].ans = min (tmp[pr].ans, tmp[pr].w - get_val (tmp[pr].y + 1) );
            }
            _loc[k++] = tmp[pr++];
        }
        for (int i = l; i < pl; ++i) {
            clear (tmp[i].y + 1);
        } 
        while (pl < mid) _loc[k++] = tmp[pl++];
        for (int i = l; i < r; ++i) {
            tmp[i] = _loc[i];
        }
    }
    
    void solve1 () { // x1 <= x2, y1 <= y2
        for (int i = 0; i < tot; i++) {
            // 操作 : -(x1 + y1), 查询 (x2 + y2) 
            if (arr[i].opt == 1) {
                tmp[i] = arr[i], tmp[i].w = + (arr[i].x + arr[i].y);
            } else {
                tmp[i] = arr[i], tmp[i].w = + (arr[i].x + arr[i].y);
            }
        }
        cdq1 (0, tot);
        for (int i = 0; i < tot; ++i) {
            if (tmp[i].opt == 2) {
                qry[tmp[i].id] = min (qry[tmp[i].id], tmp[i].ans);
            }
        }
    }
    
    void cdq2 (int l, int r) {
        if (r == l + 1) return;
        int mid = (l + r) >> 1;
        cdq2 (l, mid), cdq2 (mid, r);
    //	sort (tmp + l, tmp + mid, cmp2);
    //	sort (tmp + mid, tmp + r, cmp2);
        int pl = l, pr = mid, k = l;
        while (pr < r) {
            while (pl < mid && tmp[pl].x <= tmp[pr].x) {
                if (tmp[pl].opt == 1) {
    //				cout << "Add : " << pl << endl;
                    add_val (MaxK - tmp[pl].y, tmp[pl].w);
                }
                _loc[k++] = tmp[pl++];
            }
            if (tmp[pr].opt == 2) {
    //			cout << "Qry : " << pr << endl;
                tmp[pr].ans = min (tmp[pr].ans, tmp[pr].w - get_val (MaxK - tmp[pr].y));
            }
            _loc[k++] = tmp[pr++];
        }
    //	cout << "l = " << l << " r = " << r << endl;
    //	cout << "Lside : " << endl;
    //	for (int i = l; i < mid; ++i) {
    //		tmp[i].out ();
    //	}
    //	cout << endl << endl;
    //	cout << "Rside : " << endl;
    //	for (int i = mid; i < r; ++i) {
    //		if (i != mid) cout << ", "; tmp[i].out ();
    //	} 
    //	cout << endl << endl;
        for (int i = l; i < pl; ++i) {
            clear (MaxK - tmp[i].y);
        } 
        while (pl < mid) _loc[k++] = tmp[pl++];
        for (int i = l; i < r; ++i) {
            tmp[i] = _loc[i];
        }
    }
    
    void solve2 () { // x1 <= x2, y1 >= y2
        for (int i = 0; i < tot; i++) {
            if (arr[i].opt == 1) {
                tmp[i] = arr[i], tmp[i].w = + (arr[i].x - arr[i].y);
            } else {
                tmp[i] = arr[i], tmp[i].w = + (arr[i].x - arr[i].y);
            }
        }
        cdq2 (0, tot);
        for (int i = 0; i < tot; ++i) {
            if (tmp[i].opt == 2) {
                qry[tmp[i].id] = min (qry[tmp[i].id], tmp[i].ans);
            }
        }
    }
    
    void cdq3 (int l, int r) {
        if (r == l + 1) return;
        int mid = (l + r) >> 1;
        cdq3 (l, mid), cdq3 (mid, r);
    //	sort (tmp + l, tmp + mid, cmp3);
    //	sort (tmp + mid, tmp + r, cmp3);
        int pl = l, pr = mid, k = l;
        while (pr < r) {
            while (pl < mid && tmp[pl].x >= tmp[pr].x) {
                if (tmp[pl].opt == 1) {
                    add_val (tmp[pl].y + 1, tmp[pl].w);
                }
                _loc[k++] = tmp[pl++];
            }
            if (tmp[pr].opt == 2) {
                tmp[pr].ans = min (tmp[pr].ans, tmp[pr].w - get_val (tmp[pr].y + 1) );
            }
            _loc[k++] = tmp[pr++];
        }
        for (int i = l; i < pl; ++i) {
            clear (tmp[i].y + 1);
        }
        while (pl < mid) _loc[k++] = tmp[pl++];
        for (int i = l; i < r; ++i) {
            tmp[i] = _loc[i];
        } 
    }
    
    void solve3 () { // x1 <= x2, y1 >= y2
        for (int i = 0; i < tot; i++) {
            if (arr[i].opt == 1) {
                tmp[i] = arr[i], tmp[i].w = + (arr[i].y - arr[i].x);
            } else {
                tmp[i] = arr[i], tmp[i].w = + (arr[i].y - arr[i].x);
            }
        }
        cdq3 (0, tot);
        for (int i = 0; i < tot; ++i) {
            if (tmp[i].opt == 2) {
                qry[tmp[i].id] = min (qry[tmp[i].id], tmp[i].ans);
            }
        }
    }
    
    void cdq4 (int l, int r) {
        if (r == l + 1) return;
        int mid = (l + r) >> 1;
        cdq4 (l, mid), cdq4 (mid, r);
    //	sort (tmp + l, tmp + mid, cmp4);
    //	sort (tmp + mid, tmp + r, cmp4);
        int pl = l, pr = mid, k = l;
        while (pr < r) {
            while (pl < mid && tmp[pl].x >= tmp[pr].x) {
                if (tmp[pl].opt == 1) {
                    add_val (MaxK - tmp[pl].y, tmp[pl].w);
                }
                _loc[k++] = tmp[pl++];
            }
            if (tmp[pr].opt == 2) {
                tmp[pr].ans = min (tmp[pr].ans, tmp[pr].w - get_val (MaxK - tmp[pr].y));
            }
            _loc[k++] = tmp[pr++];
        }
        for (int i = l; i < pl; ++i) {
            clear (MaxK - tmp[i].y);
        } 
        while (pl < mid) _loc[k++] = tmp[pl++];
        for (int i = l; i < r; ++i) {
            tmp[i] = _loc[i];
        }
    }
    
    void solve4 () { // x1 <= x2, y1 >= y2
        for (int i = 0; i < tot; i++) {
            if (arr[i].opt == 1) {
                tmp[i] = arr[i], tmp[i].w = - (arr[i].y + arr[i].x);
            } else {
                tmp[i] = arr[i], tmp[i].w = - (arr[i].y + arr[i].x);
            }
        }
        cdq4 (0, tot);
        for (int i = 0; i < tot; ++i) {
            if (tmp[i].opt == 2) {
                qry[tmp[i].id] = min (qry[tmp[i].id], tmp[i].ans);
            }
        }
    }
    
    int read () {
        int s = 0, w = 1, ch = getchar ();
        while ('9' < ch || ch < '0') {
            if (ch == '-') w = -1;
            ch = getchar ();
        }
        while ('0' <= ch && ch <= '9') {
            s = s * 10 + ch - '0';
            ch = getchar ();
        }
        return s * w;
    }
    
    int main () {
    //	freopen ("data.in", "r", stdin);
    //	freopen ("data.out", "w", stdout);
        cin >> n >> m;
        memset (tree, -0x3f, sizeof (tree));
        for (int i = 0; i < n; ++i) {
            static int x, y;
            x = read (), y = read ();
            arr[tot++] = (Node) {x, y, 0, 0, 0, 1};
        }
        for (int i = 0; i < m; ++i) {
            static int opt, x, y;
            opt = read (), x = read (), y = read ();
            if (opt == 1) {
                arr[tot++] = (Node) {x, y, 0, 0, 0, opt};
            } else {
                arr[tot++] = (Node) {x, y, 0, qryid++, INF, opt};
            }
        }
        memset (qry, 0x3f, sizeof (qry));
        solve1 (); solve2 ();
        solve3 (); solve4 ();
        for (int i = 0; i < qryid; ++i) {
            printf ("%d
    ", qry[i]);
        }
    }
    
  • 相关阅读:
    Treap 树堆 容易实现的平衡树
    (转)Maven实战(二)构建简单Maven项目
    (转)Maven实战(一)安装与配置
    根据请求头跳转判断Android&iOS
    (转)苹果消息推送服务器 php 证书生成
    (转)How to renew your Apple Push Notification Push SSL Certificate
    (转)How to build an Apple Push Notification provider server (tutorial)
    (转)pem, cer, p12 and the pains of iOS Push Notifications encryption
    (转)Apple Push Notification Services in iOS 6 Tutorial: Part 2/2
    (转)Apple Push Notification Services in iOS 6 Tutorial: Part 1/2
  • 原文地址:https://www.cnblogs.com/maomao9173/p/10904083.html
Copyright © 2011-2022 走看看