Compilation: CDQ Divide and Conquer

Listen koala owner said CDQ divide and conquer her exam NOI time now yy out, too strong Orz

CDQ main partition is an idea, to deal with off-line problems.

Seniors say can be optimized DP, but I think quite a narrow range of applications, mainly processing sequence problems, the most important should be the partial order.

The main idea is to divide and conquer CDQ before a child with a sub-problem after problem solving, such as asking you a range of dichotomy, the maintenance interval left the answer section to the right of the left side of the interval to maintain answer queries. As for the operation and maintenance of the right of the left? To the next level to solve.

This limits the scope of CDQ partition, you need to modify the contribution of the operation to the inquiry are independent and affect each other.

Problem A: Mo flowers

Maintenance dimensional partial sequence.

Tree bare tree cover title, cut, gone (wrong

Tree cover tree long and boring can not write, do not write, write CDQ good tune to write CDQ

First we would like a two-dimensional partial order is how to solve: first row of a sequence according to the first dimension, the second dimension statistical answer

Three-dimensional partial order more than one dimension, or in the outermost layer of the third dimension statistics answer the second one-dimensional sets of CDQ.

Specific point, press a row of a sequence, stop by weight. Then the CDQ run, by running the merge sort b, c while maintaining the partial ordering of a data structure, where the array is a tree, while the previous merge guarantees ordered b.

#include <bits/stdc++.h>

const int N = 200000 + 233;
int n, k, ans[N];
struct Flower {int a, b, c, cnt, f;} a[N], b[N];

bool cmp(const Flower &x, const Flower &y) {
    return (x.a == y.a && x.b == y.b) ? x.c < y.c : (x.a == y.a) ? x.b < y.b : x.a < y.a;
}

struct BIT {
    int t[N];
    BIT() {memset(t, 0, sizeof(t));}
    inline void Add(int x, int v) {
        while (x <= k) t[x] += v, x += x & -x;
    }
    inline int Ask(int x) {
        int ret = 0;
        while (x) ret += t[x], x -= x & -x;
        return ret;
    }
} bit;

void CDQ(int l, int r) {
    if (l == r) return;
    int mid = (l + r) >> 1, pl = l, pr = mid + 1, p = l;
    CDQ(l, mid), CDQ(mid + 1, r);
    while (pl <= mid || pr <= r) {
        if ((a[pl].b <= a[pr].b && pl <= mid) || (pr > r)) bit.Add(a[pl].c, a[pl].cnt), b[p++] = a[pl++];
        else a[pr].f += bit.Ask(a[pr].c), b[p++] = a[pr++];
    }
    for (int i = l; i <= mid; i++) bit.Add(a[i].c, -a[i].cnt);
    for (int i = l; i <= r; i++) a[i] = b[i];
}

signed main() {
    scanf("%d%d", &n, &k);
    for (int i = 1; i <= n; i++)
        scanf("%d%d%d", &a[i].a, &a[i].b, &a[i].c), a[i].cnt = 1;
    std::sort(a + 1, a + 1 + n, cmp);
    int p = 1;
    for (int i = 2; i <= n; i++) {
        if (a[i].a == a[p].a && a[i].b == a[p].b && a[i].c == a[p].c) a[p].cnt++;
        else a[++p] = a[i];
    }
    CDQ(1, p);
    for (int i = 1; i <= p; i++) ans[a[i].f + a[i].cnt - 1] += a[i].cnt;
    for (int i = 0; i < n; i++) printf("%d\n", ans[i]);
    return 0;
}

Problem B & C: Mokia & simple questions

Double happiness

Queries easy to think of a two-dimensional matrix weights and prefix, plus the upper right corner and the lower left corner, the upper left and lower right corner lose. Query operation to be split into four.

About modification operations, contributing to a modification of the query, if and only if it is no larger than xyt inquiry, which became a three-dimensional partial order, continue CDQ.

The problem of long talk wants to know, like variable names y1 will hit, you will CE. Two solutions, one is you change a variable name, or if you're as stubborn as I am, you can open a namespace to avoid the blow.

Simple question is mandatory in Luogu online, double experience careful, you CDQ die (

#include <bits/stdc++.h>

namespace Gekoo {
    const int N = 2000000 + 233;
    int s, w, qwq, qaq, ans[N];

    struct Command {
        int opt, x, y, a, p;
    } cmd[N], tmp[N];

    struct Bit {
        int t[N];
        inline void Add(int p, int d) {
            for (; p <= w; p += p & -p) t[p] += d;
        }
        inline int Ask(int p) {
            int ret = 0;
            for (; p; p -= p & -p) ret += t[p];
            return ret;
        } 
    } BIT;

    inline int R() {
        int a = 0; char c = getchar();
        while (!isdigit(c)) c = getchar();
        while (isdigit(c)) a = a * 10 + c - '0', c = getchar();
        return a;
    }

    void CDQ(int l, int r) {
        if (l == r) return;
        int mid = (l + r) >> 1, pl = l, pr = mid + 1, p = l;
        CDQ(l, mid), CDQ(mid + 1, r);
        while (pl <= mid || pr <= r) {
            if ((cmd[pl].x <= cmd[pr].x && pl <= mid) || pr > r) {
                if (cmd[pl].opt == 1) BIT.Add(cmd[pl].y, cmd[pl].a);
                tmp[p++] = cmd[pl++];
            } else {
                if (cmd[pr].opt == 2) {
                    if (cmd[pr].p > 0) ans[cmd[pr].p] += BIT.Ask(cmd[pr].y);
                    else ans[-cmd[pr].p] -= BIT.Ask(cmd[pr].y);
                }
                tmp[p++] = cmd[pr++];
            }
        }
        for (int i = l; i <= mid; i++) 
            if (cmd[i].opt == 1) BIT.Add(cmd[i].y, -cmd[i].a);
        for (int i = l; i <= r; i++) cmd[i] = tmp[i];
    }

    signed QAQ() {
        s = R(), w = R();
        while (19260817 < 20030325) {
            int opt = R();
            if (opt == 3) break;
            if (opt == 1) cmd[++qwq].opt = 1, cmd[qwq].x = R(), cmd[qwq].y = R(), cmd[qwq].a = R();
            if (opt == 2) {
                int x1 = R(), y1 = R(), x2 = R(), y2 = R();
                ans[++qaq] = (x2 - x1 + 1) * (y2 - y1 + 1) * s;
                cmd[++qwq].opt = 2, cmd[qwq].p = qaq, cmd[qwq].x = x1 - 1, cmd[qwq].y = y1 - 1;
                cmd[++qwq].opt = 2, cmd[qwq].p = qaq, cmd[qwq].x = x2, cmd[qwq].y = y2;
                cmd[++qwq].opt = 2, cmd[qwq].p = -qaq, cmd[qwq].x = x1 - 1, cmd[qwq].y = y2;
                cmd[++qwq].opt = 2, cmd[qwq].p = -qaq, cmd[qwq].x = x2, cmd[qwq].y = y1 - 1;
            }
        }
        CDQ(1, qwq);
        for (int i = 1; i <= qaq; i++)
            printf("%d\n", ans[i]);
        return 0;
    }
}

signed main() {
    return Gekoo::QAQ();
}

Problem C: angel doll

Absolute value can not be maintained,

#include <bits/stdc++.h>

const int N = 1000000 + 233, INF = 0x3f3f3f3f;
int n, m, ans[N], real_ans[N], mx_x, mx_y;
struct Doll {
    int x, y, t, id;
    friend bool operator <(Doll x, Doll y) {
        return x.id < y.id;
    }
} d[N], tmp[N];

struct Bit {
    int t[N];
    inline void Add(int x, int d) {
        for (; x <= mx_y; x += x & -x) t[x] = std::max(t[x], d);
    }
    inline int Ask(int x) {
        int ret = -INF;
        for (; x; x -= x & -x) ret = std::max(ret, t[x]);
        return ret;
    }
    inline void Clear(int x) {
        for (; x <= mx_y; x += x & -x) t[x] = -INF;
    }
} BIT;

inline int R() {
    int a = 0; char c = getchar();
    while (!isdigit(c)) c = getchar();
    while (isdigit(c)) a = a * 10 + c - '0', c = getchar();
    return a;
}

void CDQ(int l, int r) {
    if (l == r) return;
    int mid = (l + r) >> 1, pl = l, pr = mid + 1, p = l;
    CDQ(l, mid), CDQ(mid + 1, r);
    while (pl <= mid || pr <= r) {
        if ((pl <= mid && d[pl].x <= d[pr].x) || pr > r) {
            if (d[pl].t == 1) BIT.Add(d[pl].y, d[pl].x + d[pl].y);
            tmp[p++] = d[pl++];
        }
        else {
            if (d[pr].t == 2) ans[d[pr].id] = std::max(ans[d[pr].id], BIT.Ask(d[pr].y));
            tmp[p++] = d[pr++];
        }
    }
    for (int i = l; i <= mid; i++) BIT.Clear(d[i].y);
    for (int i = l; i <= r; i++) d[i] = tmp[i];
}

signed main() {
    n = R(), m = R();
    for (int i = 1; i <= n; i++)
        d[i].x = R() + 1, d[i].y = R() + 1, d[i].t = 1, d[i].id = i, mx_x = std::max(d[i].x, mx_x), mx_y = std::max(d[i].y, mx_y);
    for (int i = 1; i <= m; i++)
        d[i + n].t = R(), d[i + n].id = i + n, mx_x = std::max(d[i + n].x = R() + 1, mx_x), mx_y = std::max(d[i + n].y = R() + 1, mx_y);
    for (int i = 1; i <= n + m; i++)
        real_ans[i] = INF, ans[i] = -INF;
    for (int i = 0; i <= mx_x + mx_y + 2; i++) BIT.t[i] = -INF;
    mx_x++, mx_y++, CDQ(1, n + m);

    std::sort(d + 1, d + 1 + n + m);
    for (int i = 1; i <= n + m; i++)
        real_ans[i] = std::min(real_ans[i], d[i].x + d[i].y - ans[i]), d[i].x = mx_x - d[i].x, ans[i] = -INF;
    CDQ(1, n + m);

    std::sort(d + 1, d + 1 + n + m);
    for (int i = 1; i <= n + m; i++)
        real_ans[i] = std::min(real_ans[i], d[i].x + d[i].y - ans[i]), d[i].y = mx_y - d[i].y, ans[i] = -INF;
    CDQ(1, n + m);

    std::sort(d + 1, d + 1 + n + m);
    for (int i = 1; i <= n + m; i++)
        real_ans[i] = std::min(real_ans[i], d[i].x + d[i].y - ans[i]), d[i].x = mx_x - d[i].x, ans[i] = -INF; 
    CDQ(1, n + m);

    std::sort(d + 1, d + 1 + n + m);
    for (int i = 1; i <= n + m; i++)
        real_ans[i] = std::min(real_ans[i], d[i].x + d[i].y - ans[i]);
    for (int i = 1; i <= n + m; i++)
        if (d[i].t == 2)
            printf("%d\n", real_ans[i]);
    return 0;
}

Guess you like

Origin www.cnblogs.com/gekoo/p/11249445.html