Notes - leftist tree

effect

Support delete, merge, query maximum or minimum (can also query the median oh)

Single time complexity \ (O (log n) \ )

basic concepts

  • Heap: binary tree

  • Empty node: no left son nodes

  • Large root heap: Each node has the right to meet the value of the node is greater than or equal her son node of the heap

  • Small heap root: root with large stack opposite heap

  • Distance node: take the right son until an empty node visited nodes

  • Leftist tree: from left son of the right son distance greater than or equal heap

nature

  • Is a large (small) heap with

  • Distance greater than or equal son left his son the right distance

  • The distance from the node to a node of the right son + 1 (not to be interpreted too much water)

  • A n tree nodes her left side \ (the root \) a distance of no more than \ (log (n + 1) -1 \)

Properties guaranteed by the last stack to the bottom of a time complexity is \ (log \) level

achieve

\(merge\)

Only you need to learn \ (merge \) that she is very simple

\ (merge \) is to merge two stacks

inline int merge(int u,int v)
    {
        if(!u||!v) return u | v;
        至少有一个是0 返回另一个 等效于u+v
        if(heap[u].val > heap[v].val)
            swap(u,v);
      
        heap[u].r = merge(heap[u].r,v);
      合并
        if(dis[heap[u].l] < dis[heap[u].r])
            swap(heap[u].l,heap[u].r);
      满足性质2
        dis[u] = dis[heap[u].r] + 1;
      算距离(性质3)
        return u;
    }

Well, in fact, now you can already \ (A \) This question is a

\(delete\)

To delete a node is equivalent to about merging the sub-tree node

Queries maximum and minimum

Each one leftist tree can only maintain a maximum and minimum of

1 obtained by the maximum and minimum properties heap root weights

Disjoint-set

The number of x and y where the number of combined bulk rootlets

Sentence utilize disjoint-set to achieve

Note To path compression

\(Code\)

Board questions

#include <cstdio>
#include <iostream>
#define reg register int
using namespace std; 
const int MAXN = 100005;
int n,m;
namespace leftist_tree
{
    struct node {int l,r,val;};
    node heap[MAXN];
    bool exist[MAXN];
    int dis[MAXN],rt[MAXN];
    inline void init()
    {
        for(reg i = 1;i <= n;i++)
            scanf("%d",&heap[i].val),rt[i] = i;
    }
    inline int merge(int u,int v)
    {
        if(!u||!v) return u | v;
        if(heap[u].val > heap[v].val)
            swap(u,v);
        heap[u].r = merge(heap[u].r,v);
        if(dis[heap[u].l] < dis[heap[u].r])
            swap(heap[u].l,heap[u].r);
        dis[u] = dis[heap[u].r] + 1;
        return u;
    }
    inline int find_set(int x)
    {
        if(rt[x] == x) return x;
        return rt[x] = find_set(rt[x]);
    }
}
using namespace leftist_tree; 
int main()
{
    scanf("%d%d",&n,&m);
    leftist_tree::init();
    while(m--)
    {
        int sit;
        scanf("%d",&sit);
        if(sit & 1)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            if(exist[u]||exist[v]) continue;
            int fu = find_set(u),fv = find_set(v);
            if(fu != fv) rt[fu] = rt[fv] = merge(fu,fv);
        } else {
            int x;
            scanf("%d",&x);
            if(exist[x])
            {
                printf("-1\n");
                continue;
            }
            x = find_set(x);
            printf("%d\n",heap[x].val);
            exist[x] = 1;
            rt[heap[x].l] = rt[heap[x].r] = rt[x] = merge(heap[x].l,heap[x].r); 
            heap[x].l = heap[x].r = dis[x] = 0;
        }
    }
    return 0;
}

The board is slightly harder problem

Enhance the look:

It does not fall into a plurality of sub-sequences obtained for each sub-sequence the median

For the sub-sequence of consecutive bits in ascending

We got her into one heap and then seek median

Seeking median

Necessary and sufficient condition is that the right to a heap of median value equal to root

We ask only this pile was half the size of the heap (heap at this point is still a large (small) heap root)

Think about it a little to be able to understand it QAQ

\(Code\)

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
#define reg register int
const int MAXN = 1e6 + 10;
typedef long long ll;
int n,num[MAXN],son[MAXN][2];
template<typename T>
inline T Read(T x)
{
    x = 0;
    int f = 1;
    char a = getchar();
    while(!isdigit(a)) {if(a == '-') f = -1;a = getchar();} 
    while(isdigit(a)) {x = (x << 1) + (x << 3) + (a ^ '0');a = getchar();}
    return x * f;
}
namespace leftist_tree {
    struct node {
        int size,lef,rig,val,rt;
    };
    node heap[MAXN];
    int dis[MAXN];
    inline int merge(int u,int v) {
        if(!u||!v) return u | v;
        if(num[u] < num[v]||(num[u] == num[v]&&v > u)) swap(u,v);
        son[u][1] = merge(son[u][1],v);
        if(dis[son[u][0]] < dis[son[u][1]]) swap(son[u][0],son[u][1]);
        dis[u] = dis[son[u][1]] + 1;
        return u;
    }
}
using namespace leftist_tree;
inline void init() {
    n = Read(1);
    dis[0] = -1;
    memset(heap,0,sizeof(heap));
    for(reg i = 1; i <= n; i++)
    {
        num[i] = Read(1) - i;   
    }
}
int cnt,b[MAXN];
ll ans;
inline void solve() {
    for(reg i = 1; i <= n; i++) {
        heap[++cnt] = (node){1,i,i,num[i],i};
        while(cnt > 1&&heap[cnt - 1].val > heap[cnt].val) {
        对于连续上升的子序列的中位数
    
            我们把她合并为一个堆 再求中位数
            cnt--;
            heap[cnt].rt = merge(heap[cnt].rt,heap[cnt + 1].rt);
            heap[cnt].size += heap[cnt + 1].size;
            heap[cnt].rig = heap[cnt + 1].rig;
            while(heap[cnt].size * 2 > heap[cnt].rig - heap[cnt].lef + 2) {
                heap[cnt].size--;
                heap[cnt].rt = merge(son[heap[cnt].rt][0],son[heap[cnt].rt][1]);
            }
          只保留一半元素
            heap[cnt].val = num[heap[cnt].rt];
        }
    }
    for(reg i = 1; i <= cnt; i++)
        for(reg j = heap[i].lef; j <= heap[i].rig; j++) {
            b[j] = heap[i].val;
            ans += 1ll * abs(b[j] - num[j]);
        }
    printf("%lld\n",ans);
}
int main() {
    init();
    solve();
    return 0;
}

Guess you like

Origin www.cnblogs.com/resftlmuttmotw/p/11627850.html