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

    【LG4169】[Violet]天使玩偶/SJY摆棋子

    题面

    bzoj权限题呀

    良心洛谷

    题解

    cdq分治

    其实题目就是说

    实时插入点,并且给定点((x,y))

    (min_{i=1}^{n})({|x-x_i|+|y-y_i|})

    我们考虑(cdq)分治,如何做呢?

    绝对值很丑,其实可以分别考虑右上、左上、左下、右下四个方向

    就可以把式子变成这样

    (min_{i=1}^{n})({(x-x_i)+(y-y_i)})

    (Rightarrow) ((x+y)-max(x_i+y_i))其中(x_i)(y_i)分别小于(x)(y)

    然后这个可以用值域树状数组维护一个前缀(max)来做

    而四个方向直接将点按照坐标轴对称过去即可

    代码

    常数大,要吸氧

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <climits> 
    using namespace std;
    namespace IO { 
        const int BUFSIZE = 1 << 20; 
        char ibuf[BUFSIZE], *is = ibuf, *it = ibuf; 
        inline char gc() { 
            if (is == it) it = (is = ibuf) + fread(ibuf, 1, BUFSIZE, stdin); 
            return *is++; 
        } 
    } 
    inline int gi() {
        register int data = 0, w = 1;
        register char ch = 0;
        while (ch != '-' && (ch > '9' || ch < '0')) ch = IO::gc();
        if (ch == '-') w = -1 , ch = IO::gc();
        while (ch >= '0' && ch <= '9') data = data * 10 + (ch ^ 48), ch = IO::gc();
        return w * data;
    }
    inline void chkmin(int &x, int y) { if (x > y) x = y; } 
    inline void chkmax(int &x, int y) { if (x < y) x = y; } 
    #define MAX_V 1000005 
    #define MAX_N 300005 
    inline int lb(int x) { return x & -x; } 
    int c[MAX_V], Lx = 0, Ly = 0; 
    void clear(int x) { while (x <= Ly) c[x] = 0, x += lb(x); } 
    int qmax(int x) { int res = 0; while (x > 0) chkmax(res, c[x]), x -= lb(x); return res; } 
    void add(int x, int v) { while (x <= Ly) chkmax(c[x], v), x += lb(x); } 
    struct Query { int t, x, y; bool fl; } q[MAX_N << 1]; int A[MAX_N << 1]; 
    inline bool cmp_t(Query a, Query b) { return a.t < b.t; } 
    inline bool cmp_x(Query a, Query b) { return (a.x == b.x) ? (a.y < b.y) : (a.x < b.x); } 
    void Div(int l, int r) { 
        if (l == r) return ; 
        int mid = (l + r) >> 1; 
        Div(l, mid); Div(mid + 1, r); 
        int j = l; 
        for (int i = mid + 1; i <= r; i++) { 
            if (q[i].fl) continue; 
            for ( ; j <= mid && q[j].x <= q[i].x; ++j) 
                if (q[j].fl) add(q[j].y, q[j].x + q[j].y); 
            int res = qmax(q[i].y); if (res) chkmin(A[q[i].t], q[i].x + q[i].y - res); 
        } 
        for (int i = l; i < j; i++) if (q[i].fl) clear(q[i].y); 
        inplace_merge(&q[l], &q[mid + 1], &q[r + 1], cmp_x); 
    } 
    int N, M; 
    void init() { sort(&q[1], &q[N + 1], cmp_t); } 
    int main () { 
        N = gi(), M = gi(); 
        for (int i = 1; i <= N; i++) { 
            int x = gi() + 1, y = gi() + 1; 
            q[i] = (Query){i, x, y, 1}; 
            chkmax(Lx, x), chkmax(Ly, y); 
        } 
        while (M--) {
        	int op = gi(), x = gi() + 1, y = gi() + 1; 
        	++N, q[N] = (Query){N, x, y, op & 1}; 
        	chkmax(Lx, x), chkmax(Ly, y); 
        } 
        for (int i = 1; i <= N; i++) A[i] = INT_MAX; ++Lx, ++Ly; 
        Div(1, N); 
        for (int i = 1; i <= N; i++) q[i].x = Lx - q[i].x; init(); Div(1, N); 
        for (int i = 1; i <= N; i++) q[i].x = Lx - q[i].x;
        for (int i = 1; i <= N; i++) q[i].y = Ly - q[i].y; init(); Div(1, N); 
        for (int i = 1; i <= N; i++) q[i].y = Ly - q[i].y;
        for (int i = 1; i <= N; i++) q[i].x = Lx - q[i].x, q[i].y = Ly - q[i].y; init(); Div(1, N); 
        for (int i = 1; i <= N; i++) 
            if (A[i] != INT_MAX) printf("%d
    ", A[i]); 
        return 0; 
    } 
    

    KDtree

    这里

  • 相关阅读:
    想要学习编程?不如来玩玩这15款游戏!总有一款适合你!
    C++ 高级教程:C++ 文件和流
    4个小众Chrome插件,最后一个互联网人必备!
    程序员必读,熬夜是如何摧残你的身体的!
    教育部将编程教育纳入中小学相关课程,编程正成为全球语言!
    Windows 比 Linux 好?我有 13 个反对理由
    程序员的十八般兵器库,捋一捋这近几年程序员们日常工作中常用的开源工具
    how to train yolov4 on custom dataset
    How to Perform Object Detection With YOLOv3 in Keras
    YOLOv4 / Scaled-YOLOv4 / YOLO
  • 原文地址:https://www.cnblogs.com/heyujun/p/10120747.html
Copyright © 2011-2022 走看看