Codeforces 675D Tree Construction (splay)

題意

往一個根爲a[0]的二叉搜索樹裏面插數,每插一個數就輸出他的父節點。

思路

根據二叉搜索樹的性質,我們插進去一個數,他的父節點肯定是比他小的最大的和比他大的最小的數裏面的兩個,然後這兩個節點找最深的那個就是他的父節點,我們可以給這些節點設置一個時間戳就能判斷先後順序了。
在找那兩個節點的時候我是直接用的splay找的,實際上我們可以直接用兩個set一個儲存負數一個儲存正數然後兩個lower_bound找到這兩個數,因爲比賽的時候比較捉急調了挺長時間再加上我對我的迭代器操作水平不怎麼自信就直接splay找了= =

代碼

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
typedef long long ll;
#define MD 1000000007
const int INF = 0x3f3f3f3f;
const double eps = 1e-8;
const int maxn = 100005;
int pre[maxn], key[maxn], ch[maxn][2], root, tot;
//父節點,鍵值,左右孩子0左1右,根節點,節點數量
int n;
void NewNode(int &r, int fa, int k)
{
    r = ++tot;
    pre[r] = fa;
    key[r] = k;
    ch[r][0] = ch[r][1] = 0;
}
void Rotate(int x, int kind)    //kind爲1時右旋,爲0左旋
{
    int y = pre[x];
    ch[y][!kind] = ch[x][kind];
    pre[ch[x][kind]] = y;
    if (pre[y])
        ch[pre[y]][ch[pre[y]][1]==y] = x;
    pre[x] = pre[y];
    ch[x][kind] = y;
    pre[y] = x;
}
void Splay(int r, int goal)
{
    while (pre[r] != goal)
    {
        if (pre[pre[r]] == goal) Rotate(r, ch[pre[r]][0]==r); //左兒子右旋右兒子左旋
        else
        {
            int y = pre[r];
            int kind = (ch[pre[y]][0] == y); //y是左兒子時kind是1,y是右兒子時kind是1
            if (ch[y][kind] == r)
            {
                Rotate(r, !kind);   //r和y左右不同時,之字形
                Rotate(r, kind);
            }
            else
            {
                Rotate(y, kind);   //r和y是一條線時,一字型
                Rotate(r, kind);
            }
        }
    }
    if (goal == 0) root = r;
}
int Insert(int k)
{
    int r = root;
    while (ch[r][key[r]<k])
    {
        //之前有過不再重複插入
        if (key[r] == k)
        {
            Splay(r, 0);
            return 0;
        }
        r = ch[r][key[r]<k];
    }
    NewNode(ch[r][key[r]<k], r, k);
    Splay(ch[r][key[r]<k], 0);
    return 1;
}
int get_small(int x)
{
    int temp = ch[x][0];
    if (temp == 0) return INF;
    while (ch[temp][1])
        temp = ch[temp][1];
    return key[temp];
}
int get_big(int x)
{
    int temp = ch[x][1];
    if (temp == 0) return INF;
    while (ch[temp][0])
        temp = ch[temp][0];
    return key[temp];
}
map<int, int> mp;

int main()
{
    //freopen("H:\\in.txt","r",stdin);
    //freopen("H:\\out.txt","w",stdout);
    while (scanf("%d", &n) != EOF)
    {
        root = tot = 0;
        int ans = 0;
        for (int i = 1; i <= n; i++)
        {
            int num;
            scanf("%d", &num);
            mp[num] = i;
            if (i == 1)
            {
                NewNode(root, 0, num);
                continue;
            }
            if (Insert(num) == 0) continue;
            int a = get_small(root);
            int b = get_big(root);
            if (mp[a] > mp[b]) printf("%d ", a);
            else printf("%d ", b);
        }
    }
    return 0;
}
發佈了78 篇原創文章 · 獲贊 1 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章