BZOJ 3196: Tyvj 1730 二逼平衡树 题解

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=3196

思路:典型树套树(最简单写法是线段树套BST),求第K最值用类似BZOJ 1901 Dynamic Ranking的方法二分,求前继将对应所有区间对应平衡树的前继求出,取最大值即可,后继求法类似前继求法。

代码(树状数组+SBT):

#include <cstdio>

#include <cstring>

#include <algorithm>

   

using namespace std;

   

#define MAXN 50001

   

struct node {

    int key,s;

    node *left,*right;

};

   

node* t[MAXN];

node* R[MAXN];

node *bank=new(node);

   

int a[MAXN];

int n,m;

   

int lowbit(int x){

    return ((~x)+1)&x;

}

   

//--------------Size_Balanced_Tree------------------

   

int left_ratote(node* &t){

    node *k=(*t).right;

    (*t).right=(*k).left;

    (*t).s=(*(*t).left).s+(*(*t).right).s+1;

    (*k).left=t;

    (*k).s=(*t).s+(*(*k).right).s+1;

    t=k;

    return 0;

}

   

int right_ratote(node* &t){

    node *k=(*t).left;

    (*t).left=(*k).right;

    (*t).s=(*(*t).left).s+(*(*t).right).s+1;

    (*k).right=t;

    (*k).s=(*(*k).left).s+(*t).s+1;

    t=k;

    return 0;

}

   

int maintain(node* &t){

    if ((*(*(*t).left).left).s>(*(*t).right).s){

        right_ratote(t);

        maintain((*t).right);

        maintain(t);

        return 0;

    }

    if ((*(*(*t).left).right).s>(*(*t).right).s){

        left_ratote((*t).left);

        right_ratote(t);

        maintain((*t).left);

        maintain((*t).right);

        maintain(t);

        return 0;

    }

    if ((*(*(*t).right).right).s>(*(*t).left).s){

        left_ratote(t);

        maintain((*t).left);

        maintain(t);

        return 0;

    }

    if ((*(*(*t).right).left).s>(*(*t).left).s){

        right_ratote((*t).right);

        left_ratote(t);

        maintain((*t).left);

        maintain((*t).right);

        return 0;

    }

    return 0;

}

   

int INSERT(int key,node* &t){

    if (t==bank){

        t=new(node);

        (*t).left=(*t).right=bank;

        (*t).s=1;

        (*t).key=key;

        return 0;

    }

    (*t).s++;

    if (key<=(*t).key){

        INSERT(key,(*t).left);

    } else INSERT(key,(*t).right);

    maintain(t);

    return 0;

}

   

int DELETE(int key,node* &t){

    if (key==(*t).key){

        if ((*t).left==bank&&(*t).right==bank){

            delete(t);

            t=bank;

            return 0;

        }

        if ((*t).left==bank){

            node *p=(*t).right;

            delete(t);

            t=p;

            return 0;

        }

        if ((*t).right==bank){

            node *p=(*t).left;

            delete(t);

            t=p;

            return 0;

        }

        right_ratote(t);

        DELETE(key,(*t).right);

        (*t).s=(*(*t).left).s+(*(*t).right).s+1;

        maintain(t);

        return 0;

    }

    if (key<(*t).key){

        DELETE(key,(*t).left);

    } else DELETE(key,(*t).right);

    (*t).s=(*(*t).left).s+(*(*t).right).s+1;

    maintain(t);

    return 0;

}

   

int get_rank(int key,node *t){

    int rec=0;

    node *p=t;

    while (p!=bank){

        if ((*p).key<key){

            rec+=((*(*p).left).s+1);

            p=(*p).right;

        } else {

            p=(*p).left;

        }

    }

    return rec;

}

 

int get_prefix(int key,node *t){

    if (t==bank){

        return -0x7fffffff;

    }

    if (key>(*t).key){

        return max(get_prefix(key,(*t).right),(*t).key);

    } else return get_prefix(key,(*t).left);

}

 

int get_suffix(int key,node *t){

    if (t==bank){

        return 0x7fffffff;

    }

    if (key<(*t).key)

       return min((*t).key,get_suffix(key,(*t).left));

    else return get_suffix(key,(*t).right);

}

   

//------Binary_Search&Binary_Index_Tree---------

   

node *range[MAXN];

int rm;

   

int GET_RANK(int key){

    int rec=0;

    for (int i=0;i++<rm;){

        rec+=get_rank(key,range[i]);

    }

    return rec;

}

 

int get_range(int l,int r){

    rm=0;

    int i=r;

    while (i>=l){

        int s=i-lowbit(i)+1;

        if (s>=l){

            range[++rm]=t[i];

            i=s-1;

        } else {

            range[++rm]=R[i];

            i--;

        }

    }

    return 0;

}

   

int get_ans(int l,int r,int k){

    get_range(l,r);

    int left=-0x7fffffff,right=0x7fffffff;

    for (int i=0;i++<rm;){

        node *p=range[i];

        while (p!=bank){

            if ((*p).key<left){

                p=(*p).right;

                continue;

            }

            if ((*p).key>right){

                p=(*p).left;

                continue;

            }

            int s=GET_RANK((*p).key);

            if (s==k-1){

                return (*p).key;

            }

            if (s<k-1){

                left=(*p).key;

                p=(*p).right;

            } else {

                right=(*p).key;

                p=(*p).left;

            }

        }

    }

    return left;

}

   

//----------------------------------------------

   

int main(){

    (*bank).s=0;

    (*bank).left=(*bank).right=bank;

    scanf("%d%d",&n,&m);

    for (int i=0;i++<n;){

        scanf("%d",&a[i]);

        t[i]=R[i]=bank;

        for (int j=i-lowbit(i);j++<i;){

            INSERT(a[j],t[i]);

        }

        INSERT(a[i],R[i]);

    }

    while (m--){

        int l,r,k,ans,i;

        int c;

        scanf("%d",&c);

        switch (c){

            case 1:

                scanf("%d%d%d",&l,&r,&k);

                get_range(l,r);

                printf("%d\n",GET_RANK(k)+1);

                break;

            case 2:

                scanf("%d%d%d",&l,&r,&k);

                printf("%d\n",get_ans(l,r,k));             

                break;

            case 3:

                int x,y;

                scanf("%d%d",&x,&y);

                i=x;

                while (i<=n){

                    DELETE(a[x],t[i]);

                    INSERT(y,t[i]);

                    i+=lowbit(i);

                }

                (*R[x]).key=y;

                a[x]=y;

                break;

            case 4:

                ans=-0x7fffffff;

                scanf("%d%d%d",&l,&r,&k);

                get_range(l,r);

                for (i=0;i++<rm;){

                    ans=max(ans,get_prefix(k,range[i]));

                }

                printf("%d\n",ans);

                break;

            case 5:

                ans=0x7fffffff;

                scanf("%d%d%d",&l,&r,&k);

                get_range(l,r);

                for (i=0;i++<rm;){

                    ans=min(ans,get_suffix(k,range[i]));

                }

                printf("%d\n",ans);

                break;

        }

    }

    return 0;

}


    原文作者:AmadeusChan
    原文地址: https://www.jianshu.com/p/73df33808099
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞