編集:CDQ分割統治

今、あまりにも強いORZをYYコアラの所有者はCDQ除算と聞くと、彼女の試験のNOI時間を征服

CDQメインパーティションは、に対処するためのアイデア、あるオフラインの問題。

主にシーケンスの問題を処理し、年配者はDPを最適化することができると言うが、私はアプリケーションの非常に狭い範囲を考えて、最も重要なのは、部分的な順序でなければなりません。

主なアイデアは、あなたの二分法の範囲を求めて、問題解決後にサブ問題と子の前にCDQを分割し、征服することで、メンテナンス間隔は、回答クエリーを維持するために、間隔の左側の右側に応答セクションを残しました。左の右の運用および保守については?次のレベルに解決します。

これは、CDQパーティションの範囲を制限し、あなたが独立しており、お互いに影響を与える問い合わせに操作の寄与を変更する必要があります。

問題A:Moの花

メンテナンス次元の部分配列。

木裸木のカバーのタイトル、カット、なくなって(間違いました

ツリーカバーツリー長くて退屈は、書くことはできません書いていない、CDQを書くためにCDQ良い曲を書きます

第一の次元に記載の配列の最初の行、第二次元統計的回答を:まず、二次元の半順序を解決する方法であるたい

三次元部分順一次元以上、又は三次元統計の最外層には、CDQの第2の1次元セットを答えます。

特定点は、配列の行を押し重量止めます。前回のマージ保証はBを命じながらCDQは、配列が木であるデータ構造の部分的な順序を維持しながら、C、マージソート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;
}

問題B&C:Mokia&簡単な質問

ダブルハピネス

2次元マトリックスの重みと接頭辞、プラス右上隅と左下隅、左上と右下の角を考えるのは簡単クエリは失われます。クエリ操作は、4つに分割します。

それは3次元部分順となったXYT問い合わせ、より大きくない場合に限り、クエリの修正に貢献についての変更操作は、CDQを続けます。

長い話の問題を知りたい、Y1がヒットする変数名のように、あなたは、CEます。2つの溶液、すなわち、変数名を変更する場合、またはあなたが私と同じ頑固なら、あなたは打撃を避けるために名前空間を開くことができます。

簡単な質問ダブル経験慎重に、オンラインLuoguに必須である、あなたCDQダイ(

#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();
}

問題C:天使の人形

絶対値が維持できません、

#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;
}

おすすめ

転載: www.cnblogs.com/gekoo/p/11249445.html