Splay tree extension tree:

Keywords: less

Example 1: P3369 [Template] General Balance Tree:

Title Description
You need to write a data structure (referable title) to maintain some numbers, which need to provide the following operations:

1. Insertion of x numbers
2. Delete the number x (if there are more than one identical number, because only one is deleted)
3. Query x ranking (ranking defined as the number of smaller than the current number + 1). If there are multiple identical numbers, because of the ranking of the smallest output)
4. Number of queries ranked xx
5. The precursor of finding x (the precursor is defined as less than X and the largest number)
6. Find the succession of x (succession is defined as the number greater than x and the smallest)
Input format
The first action n denotes the number of operations. The next n rows have two numbers opt and x, and opt denotes the ordinal number of operations (1 < opt < 6).

Output format
For operations 3, 4, 5, 63, 4, 5, 6, one number per line is output to represent the corresponding answer.

Input and Output Samples
Input #1 replication
10
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598
Output #1 replication
106465
84185
492737
Note/hint
Space-time constraints: 1000ms,128M

1.n Data Range: n < 100000

2. Data range of each number: [-{10} ^ 7, {10} ^ 7]

Source: Tyvj1728, formerly known as Ordinary Balance Tree

Thank you here.

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<string>
#include<queue>
#define ll long long
#define llu unsigned ll
using namespace std;
const int inf=0x3f3f3f3f;
const ll lnf=0x3f3f3f3f3f3f3f3f;
const int maxn=100100;
int root=0,tot=0;
struct node
{
    int son[2];//Child node
    int fa;//Parent node
    int val;//Value of the current node
    int cnt;//Number of current val
    int si;//Number of subtree nodes
}t[maxn];

void pushup(int x)
{
    t[x].si=t[t[x].son[0]].si+t[t[x].son[1]].si+t[x].cnt;
}

int get_son(int x)
{
    return x==t[t[x].fa].son[1];
}

void rot(int x)
{
    int y=t[x].fa,z=t[y].fa,k=get_son(x),w=t[x].son[k^1];
    t[y].son[k]=w,t[w].fa=y;
    t[z].son[get_son(y)]=x,t[x].fa=z;
    t[x].son[k^1]=y,t[y].fa=x;
    pushup(y),pushup(x);
}

void splay(int x,int goal=0)// Rotate x to the target goal position
{
    while(t[x].fa!=goal)
    {
        int y=t[x].fa;
        int z=t[y].fa;
        if(z!=goal)
            if(get_son(x)==get_son(y)) rot(y);
            else rot(x);
        rot(x);
    }
    if(!goal) root=x;
}

void newnode(int &now,int fa,int val)
{
    now=++tot;
    t[now].val=val;
    t[now].fa=fa;
    t[now].si=t[now].cnt=1;
    t[now].son[0]=t[now].son[1]=0;
}

void _insert(int &now,int fa,int val)
{
    if(!now) newnode(now,fa,val),splay(now);
    else if(val<t[now].val) _insert(t[now].son[0],now,val);
    else if(val>t[now].val) _insert(t[now].son[1],now,val);
    else if(val==t[now].val) t[now].cnt++,splay(now);
}

int find_x(int now,int x)//Nodes with query weight x
{
    if(t[now].son[0]&&t[now].val>x) return find_x(t[now].son[0],x);
    else if(t[now].son[1]&&t[now].val<x) return find_x(t[now].son[1],x);
    else
    {
        splay(now);
        return now;
    }
}

int find_son(int now,int k)//Query Subtree Maximum Node
{
    while(t[now].son[k]) now=t[now].son[k];
    splay(now);
    return now;
}

int pre(int x)//Precursor node
{
    int p=find_x(root,x);
    if(t[p].val<x) return p;
    return find_son(t[p].son[0],1);
}

int suf(int x)//Successor node
{
    int p=find_x(root,x);
    if(t[p].val>x) return p;
    return find_son(t[p].son[1],0);
}


void del(int x)
{
    int last=pre(x),nt=suf(x);
    splay(last),splay(nt,last);
    int p=t[nt].son[0];
    if(t[p].cnt>1)
    {
        t[p].cnt--;
        splay(p);
    }
    else
    {
        t[nt].son[0]=0;
        splay(nt);
    }
}


int get_rank_by_val(int x)
{
    int p=find_x(root,x);
    return t[t[p].son[0]].si+1;
}

int get_val_by_rank(int now,int rk)//Nodes ranked rk
{
    if(t[t[now].son[0]].si<rk&&rk<=t[t[now].son[0]].si+t[now].cnt) return now;
    else if(t[t[now].son[0]].si>=rk) return get_val_by_rank(t[now].son[0],rk);
    else return get_val_by_rank(t[now].son[1],rk-t[t[now].son[0]].si-t[now].cnt);
}


int main(void)
{
    int tt;
    scanf("%d",&tt);
    _insert(root,0,-inf),_insert(root,0,inf);
    int op,x;
    for(int i=1;i<=tt;i++)
    {
        scanf("%d%d",&op,&x);
        if(op==1) _insert(root,0,x);
        else if(op==2) del(x);
        else if(op==3) printf("%d\n",get_rank_by_val(x)-1);
        else if(op==4) printf("%d\n",t[get_val_by_rank(root,x+1)].val);
        else if(op==5) printf("%d\n",t[pre(x)].val);
        else if(op==6) printf("%d\n",t[suf(x)].val);
    }
    return 0;
}

Example 2: P3391 (Template) Literature and Art Balance Tree (Splay):

Background of topic
This is a classic template of Play, the balance tree of literature and art.

Title Description
You need to write a data structure (refer to the title) to maintain an ordered sequence, which requires the following operations: flip an interval, such as the original ordered sequence is 543 21, flip interval is [2,4], the result is 523 4 1

Input format
The first behavior n,m n denotes that the initial sequence has n numbers. This sequence is (1,2,... n_1,n) m denotes the number of flip operations.

The next m rows have two numbers [l,r] per row, guaranteeing 1 < l < R < n

Output format
Output a line of n digits, representing the original sequence after m times of transformation results

Input and Output Samples
Input #1 replication
5 3
1 3
1 3
1 4
Output #1 replication
4 3 2 1 5
Note/hint
n,m≤100000

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<string>
#include<queue>
#define ll long long
#define llu unsigned ll
using namespace std;
const int inf=0x3f3f3f3f;
const ll lnf=0x3f3f3f3f3f3f3f3f;
const int maxn=100100;
int root=0,tot=0,a[maxn];
struct node
{
    int son[2];//Child node
    int fa;//Parent node
    int val;//Value of the current node
    int cnt;//Number of current val
    int si;//Number of subtree nodes
    int rev;//Flip mark
}t[maxn];

void pushup(int x)
{
    t[x].si=t[t[x].son[0]].si+t[t[x].son[1]].si+t[x].cnt;
}

void pushdown(int x)
{
    if(t[x].rev)
    {
        t[t[x].son[0]].rev^=1;
        t[t[x].son[1]].rev^=1;
        swap(t[x].son[0],t[x].son[1]);
        t[x].rev=0;
    }
}

int get_son(int x)
{
    return x==t[t[x].fa].son[1];
}

void rot(int x)
{
    int y=t[x].fa,z=t[y].fa,k=get_son(x),w=t[x].son[k^1];
    pushdown(y),pushdown(x);
    t[y].son[k]=w,t[w].fa=y;
    t[z].son[get_son(y)]=x,t[x].fa=z;
    t[x].son[k^1]=y,t[y].fa=x;
    pushup(y),pushup(x);
}

void splay(int x,int goal=0)// Rotate x to the target goal position
{
    while(t[x].fa!=goal)
    {
        int y=t[x].fa;
        int z=t[y].fa;
        if(z!=goal)
            if(get_son(x)==get_son(y)) rot(y);
            else rot(x);
        rot(x);
    }
    if(!goal) root=x;
}

int build(int l,int r,int fa)
{
    if(l>r) return 0;
    int mid=(l+r)>>1;
    int now=++tot;
    t[now].fa=fa;
    t[now].rev=0;
    t[now].cnt=t[now].si=1;
    t[now].val=a[mid];
    t[now].son[0]=build(l,mid-1,now);
    t[now].son[1]=build(mid+1,r,now);
    pushup(now);
    return now;
}

int get_kth(int now,int rk)
{
    pushdown(now);
    if(t[t[now].son[0]].si<rk&&rk<=t[t[now].son[0]].si+t[now].cnt) return now;
    else if(t[t[now].son[0]].si>=rk) return get_kth(t[now].son[0],rk);
    else return get_kth(t[now].son[1],rk-t[t[now].son[0]].si-t[now].cnt);
}

void _reverse(int x,int y)
{
    int l=x-1,r=y+1;
    l=get_kth(root,l),r=get_kth(root,r);
    splay(l),splay(r,l);
    int pos=t[t[root].son[1]].son[0];
    t[pos].rev^=1;
}

void dfs(int now)
{
    if(!now) return ;
    pushdown(now);
    dfs(t[now].son[0]);
    if(t[now].val!=-inf&&t[now].val!=inf)
        printf("%d ",t[now].val);
    dfs(t[now].son[1]);
}


int main(void)
{
    int n,m,x,y;
    scanf("%d%d",&n,&m);
    a[1]=-inf,a[n+2]=inf;
    for(int i=2;i<=n+1;i++) a[i]=i-1;
    root=build(1,n+2,0);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&x,&y);
        x++,y++;
        _reverse(x,y);
    }
    dfs(root);


    return 0;
}

Example 3: Robotic Sort HDU - 1890:

Somewhere deep in the Czech Technical University buildings, there are laboratories for examining mechanical and electrical properties of various materials. In one of yesterday's presentations, you have seen how was one of the laboratories changed into a new multimedia lab. But there are still others, serving to their original purposes.

In this task, you are to write software for a robot that handles samples in such a laboratory. Imagine there are material samples lined up on a running belt. The samples have different heights, which may cause troubles to the next processing unit. To eliminate such troubles, we need to sort the samples by their height into the ascending order.

Reordering is done by a mechanical robot arm, which is able to pick up any number of consecutive samples and turn them round, such that their mutual order is reversed. In other words, one robot operation can reverse the order of samples on positions between A and B.

A possible way to sort the samples is to find the position of the smallest one (P1) and reverse the order between positions 1 and P1, which causes the smallest sample to become first. Then we find the second one on position P and reverse the order between 2 and P2. Then the third sample is located etc.

The picture shows a simple example of 6 samples. The smallest one is on the 4th position, therefore, the robot arm reverses the first 4 samples. The second smallest sample is the last one, so the next robot operation will reverse the order of five samples on positions 2–6. The third step will be to reverse the samples 3–4, etc.

Your task is to find the correct sequence of reversal operations that will sort the samples using the above algorithm. If there are more samples with the same height, their mutual order must be preserved: the one that was given first in the initial order must be placed before the others in the final order too.
Input
The input consists of several scenarios. Each scenario is described by two lines. The first line contains one integer number N , the number of samples, 1 ≤ N ≤ 100 000. The second line lists exactly N space-separated positive integers, they specify the heights of individual samples and their initial order.

The last scenario is followed by a line containing zero.
Output
For each scenario, output one line with exactly N integers P1 , P1 , . . . PN ,separated by a space.
Each Pi must be an integer (1 ≤ Pi ≤ N ) giving the position of the i-th sample just before the i-th reversal operation.

Note that if a sample is already on its correct position Pi , you should output the number Pi anyway, indicating that the "interval between Pi and Pi " (a single sample) should be reversed.
Sample Input
6
3 4 5 1 6 2
4
3 3 2 1
0
Sample Output
4 6 4 5 6 6
4 2 4 4

Title: Turn the decimal number of i to the position of i every time. Ask the position of the smallest number i before flipping.
We can flip the root node of i's id every time, so its left subtree is the interval it flips. Then delete it.

But there seems to be something wrong with the previous board:
I don't know why T:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<string>
#include<queue>
#include<vector>
#include<map>
#define ll long long
#define llu unsigned ll
using namespace std;
const int inf=0x3f3f3f3f;
const ll lnf=0x3f3f3f3f3f3f3f3f;
const int maxn=100100;
int root=0,tot=0;
struct node
{
    int son[2];//Child node
    int fa;//Parent node
    int val;//Value of the current node
    int cnt;//Number of current val
    int si;//Number of subtree nodes
    int rev;//Flip mark
}t[maxn];


void pushup(int x)
{
    t[x].si=t[t[x].son[0]].si+t[t[x].son[1]].si+t[x].cnt;
}

void _reveser(int x)
{
    if(!x) return ;
    swap(t[x].son[0],t[x].son[1]);
    t[x].rev^=1;
}

void pushdown(int x)
{
    if(!x) return ;
    if(t[x].rev)
    {
        _reveser(t[x].son[0]);
        _reveser(t[x].son[1]);
        t[x].rev=0;
    }
}


int get_son(int x)
{
    return x==t[t[x].fa].son[1];
}

void rot(int x,int k)
{
    int y=t[x].fa,z=t[y].fa;
    pushdown(y),pushdown(x);

    t[y].son[!k]=t[x].son[k];
    if(t[x].son[k]) t[t[x].son[k]].fa=y;

    t[x].fa=z;
    if(z) t[z].son[t[z].son[1]==y]=x;

    t[y].fa=x;
    t[x].son[k]=y;

    pushup(y),pushup(x);
}

void splay(int x,int goal=0)// Rotate x to the target goal position
{
    while(t[x].fa!=goal)
    {
        int y=t[x].fa;
        int z=t[y].fa;
        if(z==goal) rot(x,t[t[x].fa].son[0]==x);
        else
        {
            int k=(t[z].son[0]==y);
            if(t[y].son[k]==x) rot(x,!k),rot(x,k);
            else rot(y,k),rot(x,k);
        }

    }
    if(!goal) root=x;
}

void build(int &now,int l,int r,int fa)
{
    if(l>r) return ;
    int mid=(l+r)>>1;
    now=mid;
    t[now].fa=fa;
    t[now].rev=t[now].son[0]=t[now].son[1]=0;
    t[now].cnt=t[now].si=1;
    t[now].val=mid;
    build(t[now].son[0],l,mid-1,now);
    build(t[now].son[1],mid+1,r,now);
    pushup(now);

}

int find_son(int now,int k)
{
    for(pushdown(now);t[now].son[k];pushdown(now)) now=t[now].son[k];
    splay(now,root);
    return now;
}

struct nn
{
    int x,id;
    friend bool operator <(const nn&a,const nn&b)
    {
        if(a.x==b.x) return a.id<b.id;
        else return a.x<b.x;
    }
}a[maxn];

void del_root()
{
    pushdown(root);
    if(!t[root].son[0])
    {
        root=t[root].son[1];
        t[root].fa=0;
        return ;
    }

    int x=find_son(t[root].son[0],1);
    t[x].son[1]=t[root].son[1];
    t[t[root].son[1]].fa=x;
    t[x].fa=0;
    root=x;
    pushup(root);


}

int main(void)
{
    int n,x;
    while(scanf("%d",&n),n)
    {

        for(int i=1;i<=n;i++)
            scanf("%d",&a[i].x),a[i].id=i;
        sort(a+1,a+n+1);

        root=0;
        build(root,1,n,0);

        for(int i=1;i<=n;i++)
        {
            if(i!=1) putchar(' ');
            splay(a[i].id);
            printf("%d",t[t[root].son[0]].si+i);
            _reveser(t[root].son[0]);
            del_root();
        }
        putchar('\n');
    }

    return 0;
}

Posted by Addos on Sun, 15 Sep 2019 06:57:41 -0700