[BZOJ2716][Violet 3]天使玩偶 CDQ分治+树状数组

来源:互联网 发布:自考还是网络教育 编辑:程序博客网 时间:2024/05/22 09:45

按时间分治,把每个询问拆成四个方向的查询,这样曼哈顿距离可以直接用减法得到
一维时间分治,二维x坐标排序,三维y坐标树状数组

#include <cstdio>#include <algorithm>using namespace std;const int maxn = 1000000 + 10;const int INF = 1000000000;int max_x;int ans[maxn];struct BIT {    int c[maxn];    int lowbit(int x) {        return x & (-x);    }    void modify(int x, int d) {        while(x <= max_x) {            c[x] = max(c[x], d);            x += lowbit(x);        }    }    int query(int x) {        int ret = 0;        while(x > 0) {            ret = max(ret, c[x]);            x -= lowbit(x);        }        return ret;    }    void clear(int x) {        while(x <= max_x) {            c[x] = 0;            x += lowbit(x);        }    }} bit;struct Node {    int x, y, k, id;    bool operator < (const Node& rhs) const {        if(x != rhs.x) return x < rhs.x;        return id < rhs.id;    }} A[maxn];#define a A[i]#define b A[j]struct CDQ {    int n;    Node T[maxn];    void init(int n) {        this->n = n;        sort(A+1, A+n+1);    }    void solve(int L, int R) {        if(L >= R) return;        int M = (L+R) >> 1;        int i, j, p = L, q = M+1;        for(i = L; i <= R; i++) if(a.id <= M) T[p++] = a; else T[q++] = a;        for(i = L; i <= R; i++) A[i] = T[i];        solve(L, M);        i = M+1; j = L;        for(; i <= R; i++) if(a.k == 2) {            for(; j <= M && b.x <= a.x; j++) if(b.k == 1)                bit.modify(b.y, b.x+b.y);            int t = bit.query(a.y);            if(t) ans[a.id] = min(ans[a.id], a.x+a.y-t);        }        for(i = L; i < j; i++) if(a.k == 1)            bit.clear(a.y);        solve(M+1, R);        merge(A+L, A+M+1, A+M+1, A+R+1, T+L);        for(i = L; i <= R; i++) A[i] = T[i];    }} cdq;int main(){    int n, m;    scanf("%d %d", &n, &m);    for(int i = 1; i <= n; i++) {        scanf("%d %d", &a.x, &a.y);        a.x++; a.y++; a.id = i; a.k = 1;        max_x = max(max_x, max(a.x, a.y));    }    for(int i = n+1; i <= n+m; i++) {        scanf("%d %d %d", &a.k, &a.x, &a.y);        a.x++; a.y++; a.id = i;        max_x = max(max_x, max(a.x, a.y));    }    max_x++; n += m;    for(int i = 1; i <= n; i++) ans[i] = INF;    cdq.init(n); cdq.solve(1, n);    for(int i = 1; i <= n; i++) a.x = max_x - a.x;    cdq.init(n); cdq.solve(1, n);    for(int i = 1; i <= n; i++) a.y = max_x - a.y;    cdq.init(n); cdq.solve(1, n);    for(int i = 1; i <= n; i++) a.x = max_x - a.x;    cdq.init(n); cdq.solve(1, n);    for(int i = 1; i <= n; i++)        if(ans[i] != INF) printf("%d\n", ans[i]);    return 0;}
0 0
原创粉丝点击