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]);
        }
    }
    
  • 相关阅读:
    C# 内存映射研究学习
    js Promise async await 学习研究
    js 字节数组转数字以及数字转字节数组
    C# 生成一个当前程序唯一的短字符串
    C# FileStream 读取大文件时ReadByte和Read的速度对比
    用一个数维护最多32个可叠加状态,比如权限的状态,既有“读”,又有“写”
    大牛干货:100条Unity基础小贴士
    Unity教程之-Unity3d移动平台性能优化专题(12):面板的设置
    Unity ShaderLab学习总结
    (转)【Unity技巧】Unity中的优化技术
  • 原文地址:https://www.cnblogs.com/maomao9173/p/10904083.html
Copyright © 2011-2022 走看看