[研究ノート]スプレイエントリ(更新)

免責条項:すべてのエッセイは、情報ネットワークや他のブログの光です。このブログは、ブロガーが唯一の疑いの場合には、彼らの理解と書き込みを深めたいとブロガーである✧議論する歓迎0.9(「ᗜ」)و✧*。

序文

最後に学びました 眠っていました \(スプレイ\) 私は、以前のスケープゴートツリーのことを学んだので、ハード、おそらく、それを学ぶためにすることを、長い時間のためにあるため、常にdalaoので、それは深い恐怖を持っていることを、このジョークを聞いた...しかし、ありませんか?(スケープゴートツリーは555本当に痛いですこちら)

テンプレート

P3369 [テンプレート]一般的なバランスの取れたツリー

修正された変数:

\(エッジ\) -このノードの値

\(TOT \) -重複ノードの数

\(息子[0/1] \) -左と右の息子の息子

\(FA \) -ノードの父

\(サイズ\) -サブツリーのサイズ

struct ndoe{
    int tot, size, son[2], fa, edge;
}tree[N]; 

(x)は(ドット付き)を追加します。

1.特別なポイントを探します

2.解析\(X \)特定のノードと値

  1)に等しく、直接\(++ \ TOT \)

  2)新しいノード、更新変数を等しくありません

void add(int x) 
{
    int u = root, fa = 0;
    while(u && tree[u].edge != x)
        fa = u, u = tree[u].son[x > tree[u].edge];
    if(u) ++ tree[u].tot;
    else
    {
        u = ++ num;
        if(fa) tree[fa].son[x > tree[fa].edge] = u;
        tree[u].edge = x, tree[u].size = tree[u].tot = 1, tree[u].fa = fa;
    }
    splay(u, 0);
}

デル(X)(点の削除):

1.検索します\(xと\)の前身の後継者

2.前駆\(スプレイ\)ルートノードに、後継\(スプレイ\)息子の前駆体として

3.息子は、このノード番号か否か、削除する後続の点を残しました

  1)のみのものより数の大きいを除去し、その後\(スプレイ\)

  2)の数は、直接削除しました

void del(int x)
{
    int xpre = next(x, 0), xnxt = next(x, 1);
    splay(xpre, 0), splay(xnxt, xpre);
    int u = tree[xnxt].son[0];
    if(tree[u].tot > 1) -- tree[u].tot, splay(u, 0);
    else tree[xnxt].son[0] = 0;
}

スプレイ((X、ゴール)\(X \)にねじ込ま\(目標\)の息子):

1.裁判官\(X \)かどうか(目標\)\息子

  1)そのことが決定され、ない\(X \)とその親、別の行の祖先かどうか、\ \(スプレイ)

  2)それは、それが判断されている\(X \)ルートが更新された場合、および

void splay(int x, int goal)
{
    while(tree[x].fa != goal)
    {
        int y = tree[x].fa, z = tree[y].fa;
        if(z != goal) ((tree[z].son[0] == y) ^ (tree[y].son[0] == x)) ? rotate(x) : rotate(y);
        rotate(x);
    } 
    if(! goal) root = x;
}

回転(X)(回転のみ)。

1.更新\(X \)\(Z \)親子関係

2.更新\(Y \)と(\(X- \)元と\(Y \)父と息子の関係息子に相当)

3.更新\(X \)\(Y \)親子関係の

4. \(更新\ X、Y \)

void rotate(int x)
{
    int y = tree[x].fa, z = tree[y].fa, k = (tree[y].son[1] == x);
    tree[z].son[tree[z].son[1] == y] = x, tree[x].fa = z;
    tree[y].son[k] = tree[x].son[k ^ 1], tree[tree[x].son[k ^ 1]].fa = y;
    tree[x].son[k ^ 1] = y, tree[y].fa = x;
    update(y), update(x);
}

プレ(X)(前駆体):

1. \(X \)がルートになり

左サブツリーへ2.左サブツリーは、それは数を表しよりも小さくありません

結局のところ3.左のサブツリー右部分木港への道(最大見つけます。)

NXT(x)は、(後継者):

1. \(X \)がルートになり

右部分木に右の子を持っている2.、それが表す数よりも大きくはありません

一番左と右のサブツリー港(最小を探してください)にサブツリーを入力した後3。

int next(int x, int f)//我把pre和nxt写到一起啦,实际上是一样的
{
    find(x);
    int u = root;
    if((tree[u].edge > x && f) || (tree[u].edge < x && (! f))) return u;
    u = tree[u].son[f];
    while(tree[u].son[f ^ 1]) u = tree[u].son[f ^ 1];
    return u;
}

(x)は(ヘルパー)を見つけます:

1.値を探しすることに等しい\(X \)ノードこと

前記ルートノードはに回転されます

void find(int x)
{
    int u = root;
    if(! u) return;
    while(tree[u].son[x > tree[u].edge] && tree[u].edge != x)
        u = tree[u].son[x > tree[u].edge];
    splay(u, 0);
}

クエリ(x)は(k番目の最大の数字):

1.最初のツリー全体を判断する\(サイズが\)に等しいより大きい(X \)\、そうでない場合は存在しません

2. 3例を議論し続けます。

  1)左のサブツリー\(サイズ\)よりも大きい\ X-(\)は、左のサブツリーに行きます

  2)よりもノード数+数以上の左サブツリー\ X(\)は、このノードの値が直接返されます

  3)更新\(X- \) 右のサブツリーに行きます

int query(int x)
{
    int u = root;
    if(tree[u].size < x) return 0;
    while(1)
    {
        int y = tree[u].son[0];
        if(x <= tree[y].size) u = y;
        else if(x <= tree[y].size + tree[u].tot) return tree[u].edge;
        else x -= (tree[y].size + tree[u].tot), u = tree[u].son[1];
    }
}

おすすめ

転載: www.cnblogs.com/Bn_ff/p/12275990.html