Luogu P4169 [Violet]天使玩偶/SJY摆棋子

馋奶兔 提交于 2020-02-06 03:17:56

学了不清真的\(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\n", qry[i]);
    }
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!