ツリーの議長 - 小kのダイナミックレンジ

ツリーの議長-のダイナミックレンジ\(K \)

ここでのテンプレートのタイトルロス・バレー2617

まず、いくつかの質問のまとめを行います。

この記事を読ん間隔k番目のテンプレートのタイトルで、ある財団会長ツリーを、必要とします。

静的全体のk番目:

どのような小さなKを探しているのは、時間の複雑\(O(nlogn)\)

ダイナミック全体のk番目:

時間複雑で重量のセグメントツリーのメンテナンス\(O(nlogn)\)

静的間隔k番目:

会長ツリーのメンテナンス、時間複雑\(O(nlogn)\)

ダイナミックレンジのk番目:

これはタイトルです。

リコールは、木の会長は、まだk番目の間隔を維持していますか。

持続可能なツリーラインの確立後、k番目の思考クエリー間隔とプレフィックスを使用。

私たちは、動作範囲のk番目のバンド、接頭辞を変更したいので、キーです。

どのようなデータ構造を使用してメンテナンスや一般的な接頭辞、サポートの問い合わせや変更操作で私たち、?

  • フェンウィックツリー/ツリーライン。

今回私たちは、一般的に、ツリーの動的会長と木の会長の概念持つデータ構造すでに多少異なる上を。

  • 会長の動的なツリー:ツリーのカバーの木
  • 静的会長ツリー:永続的な重量区分の木も

どのセットが問題ではなく、単に考える見つけることができ、我々は体重セグメントツリー(ルート)を維持するために、各ノード配列ツリー配列(内側の)層のための木を維持、我々はこの問題を解決することができます。

  • 修理の操作:
    • デジタルの位置場合\(a_iを= xは\)に変更(Y- \)\、次いで外側フェンウィックツリーに、我々は変更する必要があり、\(LOGNを\)ノード、および各ノードの(Aの代わりに重量セグメントツリー)、それぞれ\(logN個\)は、複雑さが変更されるので、影響を受けるノード\(O((logN個)^ 2)\)
  • 検索操作:
    • \([L、R] \ ) 、レッツは、この間隔の間に抽出照会(LOGN \)\ルートノード、および、静的議長ツリーに求めて質問の範囲変換(K \)\小。
    • 時間の複雑さはある\(O((logN個)^ 2)\)

総時間複雑そう\(O(N(LOGN) ^ 2)\) で。

次は、問題空間のいくつかを解決します。

私たちは、あるツリーラインスペースの複雑さを知っている(O(4N)\)\、つまり、\(O(N)\) フェンウィックツリーの複雑さがある(\ O(N))\そしてそうやって、スペースの複雑さに達した\(O(^ N-2)\)

最適化する方法を考えてみて?

私達はちょうど重量みなさ完全なセグメントツリーに基づいて、各ノードまで開くように、空間的な複雑さを計算します。

我々規模のクエリ/変更操作です\((LOGN)^ 2 \ ) レベル。

これは、動的に開いポイントではありません。

私たちのためにアクセスすることができ、そして問題に関することはできないノード作成、アクセスノードへ。

取り付け\(luogu2617 \)コード。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+10;
int n, m, a[maxn], b[maxn<<1], len;

struct Query
{
    int op;
    int i, j, k;
}q[maxn];

//1e5的log大概在20左右 20*20=400
int sum[maxn*400];
int ls[maxn*400];
int rs[maxn*400];
int rt[maxn*400];
int tot;

void update_SgT(int &rt, int l, int r, int x, int val)
{
    if(!rt) rt = ++tot;
    if(l == r)
    {
        sum[rt] += val;
        return;
    }
    int mid = (l+r) >> 1;
    if(x <= mid) update_SgT(ls[rt], l, mid, x, val);
    else update_SgT(rs[rt], mid+1, r, x, val);
    sum[rt] = sum[ls[rt]] + sum[rs[rt]];
}

inline int lowbit(int x){
    return x&(-x);
}

void update_BIT(int pos, int x, int val)
{
    for(int i = pos; i <= n; i += lowbit(i))
        update_SgT(rt[i], 1, len, x, val);
}

///提取区间线段树的根节点
int rt1[maxn], rt2[maxn], cnt1, cnt2;
void locate(int l, int r)
{
    cnt1 = cnt2 = 0;
    for(int i = l-1; i; i -= lowbit(i))
        rt1[++cnt1] = rt[i];
    for(int i = r; i; i -= lowbit(i))
        rt2[++cnt2] = rt[i];
}

int ask(int l, int r, int k)
{
    if(l == r) return l;
    int mid = (l+r) >> 1;
    int suml = 0;
    for(int i = 1; i <= cnt1; i++)
        suml -= sum[ls[rt1[i]]];
    for(int i = 1; i <= cnt2; i++)
        suml += sum[ls[rt2[i]]];
    if(suml >= k)
    {
        for(int i = 1; i <= cnt1; i++)
            rt1[i] = ls[rt1[i]];
        for(int i = 1; i <= cnt2; i++)
            rt2[i] = ls[rt2[i]];
        return ask(l, mid, k);
    }
    else
    {
        for(int i = 1; i <= cnt1; i++)
            rt1[i] = rs[rt1[i]];
        for(int i = 1; i <= cnt2; i++)
            rt2[i] = rs[rt2[i]];
        return ask(mid+1, r, k-suml);
    }

}


int main()
{
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i++)
    {
        scanf("%d", &a[i]);
        b[++len] = a[i];
    }

    char op[2];
    for(int i = 1; i <= m; i++)
    {
        scanf("%s", op);
        if(op[0] == 'Q')
        {
            q[i].op = 0;
            scanf("%d%d%d", &q[i].i, &q[i].j, &q[i].k);
        }
        else
        {
            q[i].op = 1;
            scanf("%d%d", &q[i].i, &q[i].k);
            b[++len] = q[i].k;
        }
    }

    //数值离散化
    sort(b+1, b+1+len);
    len = unique(b+1, b+1+len)-b-1;
    for(int i = 1; i <= n; i++)
        a[i] = lower_bound(b+1, b+len+1, a[i])-b;
    for(int i = 1; i <= m; i++)
        if(q[i].op) q[i].k = lower_bound(b+1, b+len+1, q[i].k)-b;

    //建树(动态开点形式)
    for(int i = 1; i <= n; i++)
        update_BIT(i, a[i], 1);

    for(int i = 1; i <= m; i++)
    {
        if(q[i].op)
        {
            update_BIT(q[i].i, a[q[i].i], -1);
            a[q[i].i] = q[i].k;
            update_BIT(q[i].i, q[i].k, 1);
        }
        else
        {
            locate(q[i].i, q[i].j);
            int ans = b[ask(1, len, q[i].k)];
            printf("%d\n", ans);
        }
    }

    return 0;
}

おすすめ

転載: www.cnblogs.com/zxytxdy/p/12375599.html