competitive-programing

This documentation is automatically generated by online-judge-tools/verification-helper

View the Project on GitHub Astral-23/competitive-programing

:warning: splay_tree(set) トップダウンにsplay
(Others/splayset.cpp)

Code

template<typename X>
struct splay_set {
    struct node_t {
            X val;
            X acc;
            int sum = 0;
            node_t* lch;
            node_t* rch;
            node_t(X v):  val(v), acc(v) {
                sum = 1;
                lch = nullptr;
                rch = nullptr;
            }
    };
    using NODE = node_t;
    NODE* root = nullptr;//Splay木の根を表すノード。
    long long size_of_tree = 0;//木に登録されている要素数を返す。
    int pre = 0;
    splay_set(){}

    private:

        long long count(NODE* now) {return now == nullptr ? 0 : now -> sum;}
        X acc(NODE* now) {return !now ? X() : now -> acc;}

        NODE* pushup(NODE* now) {
            if(now != nullptr) {
                now -> sum = count(now -> lch) + count(now -> rch) + 1;
                now -> acc = acc(now -> lch) + now -> val + acc(now -> rch);
            }
            return now;
        }


        NODE* rotate(NODE* now, int b) {//ノードnowを回転させる処理。b = 1で右回転、 b = 0で左回転。」
            if(b==1) {
                NODE* s = now -> lch;
                now -> lch = s -> rch;
                s -> rch = now;
                pushup(now), pushup(s);
                return s;//戻り値は、回転した後nowの位置にくるノードのポインタ。
            }
            else {
                NODE* s = now -> rch;
                now -> rch = s -> lch;
                s -> lch = now;
                pushup(now), pushup(s);
                return s;
            }
        }
        /*

        NODE* splay_sub_pos(NODE* now, int pos, pair<int, NODE*>& history, bool& found) {
            if(now == nullptr) {
                found = false;
                return now;
            } 
            if(count(now -> lch) + 1 == pos) {
                return now;
            }

            int b = 1;
            if(count(now -> lch) + 1 < pos) {
                pos -= count(now -> lch) + 1;
                now -> rch = splay_sub_pos(now -> rch, pos, history, found);
                pushup(now);
            }
            else {
                b = 0, now -> lch = splay_sub_pos(now -> lch, pos, history, found);
                pushup(now);
            } 

            if(!found) return now;

            auto [pb, pn] = history;
            if(pn == nullptr) history = make_pair(b, now);
            else {
                history = make_pair(-1, nullptr);
                if(b == pb) {
                    now = rotate(now, 1 - b);
                    now = rotate(now, 1 - b);
                }
                else {
                    if(b==1) now -> rch = rotate(pn, 1 - pb);
                    else now -> lch = rotate(pn, 1 - pb);
                    pushup(now);
                    now = rotate(now, 1 - b);
                }
            }
            return now;
        }*/

        NODE* splay_sub(NODE* now, const X& x, pair<int, NODE*>& history, bool& found) {
            if(now == nullptr) {
                found = false;
                return now;
            } 
            if(now -> val == x) {
                return now;
            }

            int b = 1;
            if(x > now -> val) {
                now -> rch = splay_sub(now -> rch, x, history, found);
                pushup(now);
            }
            else if(x < now -> val) {
                b = 0, now -> lch = splay_sub(now -> lch, x, history, found);
                pushup(now);
            } 

            if(!found) return now;

            auto [pb, pn] = history;
            if(pn == nullptr) history = make_pair(b, now);
            else {
                history = make_pair(-1, nullptr);
                if(b == pb) {
                    now = rotate(now, 1 - b);
                    now = rotate(now, 1 - b);
                }
                else {
                    if(b==1) now -> rch = rotate(pn, 1 - pb);
                    else now -> lch = rotate(pn, 1 - pb);
                    pushup(now);
                    now = rotate(now, 1 - b);
                }
            }
            return now;
        }

        void splay(NODE* now, const X& x) {
            bool found = true;
            pair<int, NODE*> h(-1, nullptr);
            root = splay_sub(now, x, h, found);
            if(found && h.second != nullptr) {
                root = rotate(root, 1 - h.first);
            }
            return ;
        }
        /*
        void splay_pos(NODE* now, int pos) {
            bool found = true;
            pair<int, NODE*> h(-1, nullptr);
            root = splay_sub_pos(now, pos, h, found);
            if(found && h.second != nullptr) {
                root = rotate(root, 1 - h.first);
            }
            return ;

        }*/
 
 
        NODE* change__(NODE* now, X& x) {//現在見ているノード | 挿入する値
            if(now == nullptr) {
                size_of_tree++;
                return new NODE(x);
            }

            if(now -> val == x) return now;


            if(x > now -> val) {
                now -> rch = change__(now -> rch, x);
                pushup(now);
                return now;
            }
            else {
                now -> lch = change__(now -> lch, x);
                pushup(now);
                return now;
            }
        }

       
        NODE* find_max_only(NODE* now) {//nowを根とする部分木の中で最大の要素を持つノードを返す。この時、splay操作は行わない。
           if(now == nullptr) return now;
           NODE* res = now;
           while(res -> rch != nullptr) res  = res -> rch;
           return res;
        }

        NODE* find_min_only(NODE* now) {//nowを根とする部分木の中で最小の要素を持つノードを返す。この時、splay操作は行わない。
           if(now == nullptr) return now;
           NODE* res = now;
           while(res -> lch != nullptr) res = res -> lch;
           return res;
        }


        NODE* erase__(NODE*now, X& x){//削除ノードまで降っていき、削除が完了次第葉の方から再構成する。
            if(now == nullptr) return now;
            if(x < now -> val) {
                now -> lch = erase__(now -> lch, x);
                pushup(now);
            }
            else if(x > now -> val) {
                now -> rch = erase__(now -> rch, x);
                pushup(now);
            }
            else {
                if(now -> lch == nullptr) {//左に子がない時
                    NODE* tmp = now -> rch;
                    delete now;
                    size_of_tree--;
                    return tmp;
                }
                else if(now -> rch == nullptr) {//右に子がない時
                    NODE* tmp = now -> lch;
                    delete now;
                    size_of_tree--;
                    return tmp;
                } else {//右にも左にも子がある時
                    NODE* tmp = find_max_only(now -> lch);//左子孫の最大値
                    now -> val = tmp -> val;
                    now -> lch = erase__(now -> lch, tmp -> val);//移動したノードを削除。(ポインタの操作に注意)
                    pushup(now);
                }
            }
            return now;//現在のノードまで削除の作業が完了したらば、更新された現在のノードを返して終了。
        }


        void lower_bound_val__(NODE*now, X& x, X& res) {//x以上で最小val
        //前提:その様な値が存在する。
            if(now -> val == x) {
                res = x;
                return;
            }
            if(x < now -> val) {//答えは、min(now, nowの左子孫の中でx以上の最小の要素)
                res = min(res, now -> val);
                if(now -> lch != nullptr) lower_bound_val__(now -> lch, x, res);
            }
            else {//答えは、右子孫の中でx以上の最小の値
                if(now -> rch != nullptr)  lower_bound_val__(now -> rch, x, res);//右に子が存在しないという事はない。
            }
            return;
        }

        void upper_bound_val__(NODE*now, X& x, X& res) {//x超過で最小val
        //前提:その様な値が存在する。
            if(x < now -> val) {//答えは、min(now, nowの左子孫の中でxより大きい最小の要素)
                res = min(res, now -> val);
                if(now -> lch != nullptr) upper_bound_val__(now -> lch, x, res);
            }
            else {//答えは、右子孫の中でxより大きいの最小の値
                if(now -> rch != nullptr)  upper_bound_val__(now -> rch, x, res);//右に子が存在しないという事はない。
            }
            return;
        }
      
      
        void lower_left_bound_val__(NODE* now, X& x, X& res) {//x以下で最大val
        //前提:その様な値が存在する。
            if(now -> val == x) {
                res = x;
                return;
            }
            if(x < now -> val) {//左
                if(now -> lch != nullptr) lower_left_bound_val__(now -> lch, x, res);
            }
            else {
                res = max(res, now -> val);
                if(now -> rch != nullptr) lower_left_bound_val__(now -> rch, x, res);

            }
        }

        void upper_left_bound_val__(NODE* now, X& x, X& res) {//x未満で最大val
        //前提:その様な値が存在する。
            if(x <= now -> val) {//左
                if(now -> lch != nullptr) upper_left_bound_val__(now -> lch, x, res);
            }
            else {
                res = max(res, now -> key);
                if(now -> rch != nullptr) upper_left_bound_val__(now -> rch, x, res);
            }
        }

        NODE* lower_bound__(X x) {//x以上で最小、存在しないならnullptr
            if(size_of_tree==0) return nullptr;
            NODE* M = find_max_only(root);
            X t = M -> val;
            if(t < x) return nullptr;//x以上の値は存在しない。
            lower_bound_val__(root, x, t);
            splay(root, t);
            return root;
        }

        NODE* upper_bound__(X x) {//k超過で最小、存在しないならnullptr
            if(size_of_tree==0) return nullptr;
            NODE* M = find_max_only(root);
            X t = M -> val;
            if(t <= x) return nullptr;
            upper_bound_val__(root, x, t);
            splay(root, t);
            return root;
        }

        NODE* lower_left_bound__(X x) {//k以下で最大。
            if(size_of_tree==0) return nullptr;
            NODE* m = find_min_only(root);
            X t = m -> val;
            if(t > x) return nullptr;
            lower_left_bound_val__(root, x, t);
            splay(root,t);
            return root;
        }

        NODE* upper_left_bound__(X x) {//k未満で最大。
            if(size_of_tree==0) return nullptr;
            NODE* m = find_min_only(root);
            X t = m -> val;
            if(t >= x) return nullptr;
            upper_left_bound_val__(root, x, t);
            splay(root, t);
            return root;
        }

        NODE* ith_element__(NODE* now, long long i) {
            long long ls = count(now -> lch);
            if(ls + 1 <= i && i <= ls + 1) {
                return now;
            }
            else if(ls >= i) return ith_element__(now -> lch, i);
            else return ith_element__(now -> rch, i - 1 - ls);
        }

        NODE* max_element__() {//最大のkey、存在しないならnullptr
            NODE* tar = find_max_only(root);
            if(tar == nullptr) return tar;
            pair<int, NODE*> h (-1, nullptr);
            splay(root , tar -> val);
            return root;
        }

        NODE* min_element__() {//最小のkey、存在しないならnullptr
            NODE* tar = find_min_only(root);
            if(tar == nullptr) return tar;
            pair<int, NODE*> h (-1, nullptr);
            splay(root , tar -> val);
            return root;
        }

        NODE* lower_sum_left__(NODE* now, X S, int L) {
            X now_sum = X();
            if(L != 1) {
                S = S + accL(L-1);
            }
            if(S > acc(root)) return nullptr;
            while(1) {
                X tmp = now_sum + acc(now -> lch);
                if(tmp >= S) now = now -> lch;
                else {
                    tmp += now -> val;
                    if(tmp >= S) {
                        splay(root, now->val);
                        return root;
                    }
                    else {
                        now_sum = tmp;
                        now = now -> rch;
                    }
                }
            }
        }

        NODE* upper_sum_left__(NODE* now, X S, int L) {
            X now_sum = X();
            if(L != 1) {
                S = S + accL(L-1);
            }
            if(S >= acc(root)) return nullptr;
            while(1) {
                X tmp = now_sum + acc(now -> lch);
                if(tmp > S) now = now -> lch;
                else {
                    tmp += now -> val;
                    if(tmp > S) {
                        splay(root, now->val);
                        return root;
                    }
                    else {
                        now_sum = tmp;
                        now = now -> rch;
                    }
                }
            }
        }

        NODE* next(NODE*& now) {//次のkey、存在しないならnullptr
            if(now == nullptr) return now;
            else return upper_bound__(now -> val);
        }


        NODE* prev(NODE*& now) {//前のkey。存在しなければnullptr
            if(now == nullptr) return now;
            else return upper_left_bound__(now -> val);
        }

        void in_order__(NODE* now, vector<X>& res) {
            if(now == nullptr) return;
            in_order__(now -> lch, res);
            res.push_back(now -> val);
            in_order__(now -> rch, res);
            return;
        }



    public:


        void insert(X x) {
            pushup(root);
            change(x);
        }

        void erase(X x) {//存在しなかった場合、何もしない。
            pushup(root);
            root = erase__(root, x);
        }

        bool find(X x) {
            pushup(root);
            splay(root,x);
            if(root == nullptr || root -> val != x) return false;
            return true;
        }

        int count(X x) {
            pushup(root);
            splay(root, x);
            if(root == nullptr || root -> val != x) return 0;
            return 1;
        }


        
        void change(X x) {//xを挿入)
            pushup(root);
            root = change__(root, x);
            splay(root, x);//根を更新。
            return;
        }

  
        int size() {
            return size_of_tree;
        }

        bool empty() {
            return size_of_tree == 0;
        }

        
        bool next(X x, X& res) {//次のkey。存在しないならfalse。結果はresに渡される。
            pushup(root);
            NODE* r = upper_bound__(x);
            if(r==nullptr)return false;
            else {
                res = r -> val;
                return true;
            }
        }

        
        bool prev(X x, X& res) {//前のkey.存在しないならfalse。結果はresに渡される。
            pushup(root);
            NODE* r = upper_left_bound__(x);
            if(r==nullptr)return false;
            else {
                res = r -> val;
                return true;
            }
        }

        bool ith_element(long long i, X& res) {
            pushup(root);
            if(count(root) < i) return false;
            else {
                NODE* tar = ith_element__(root, i);
                res = tar -> val;
                return i;
            }
        }

        long long get_order(X& x) {
            pushup(root);
            splay(root, x);
            if(root == nullptr || root -> val != x) return -1LL;
            else return count(root -> lch) + 1;
        }

        bool max_element(X& res) {//最大のkey
            pushup(root);
            NODE* tar = max_element__();
            if(tar == nullptr) return false;
            else {
                res =  tar -> val;
                return true;
            }
        }

        bool min_element(X& res) {//最小のkey
            pushup(root);
            NODE* tar = min_element__();
            if(tar == nullptr) return false;
            else {
                res =  tar -> val;
                return true;
            }
        }

        bool lower_bound(X x, X& res) {//x以上で最小key
            pushup(root);
            NODE* r = lower_bound__(x);
            if(r == nullptr) return false;
            else {
                res = r -> val;
                return true;
            }
        }

        bool upper_bound(X x, X& res) {//k超過で最小となる
            pushup(root);
            NODE* r = upper_bound__(x);
            if(r == nullptr) return false;
            else {
                res = r -> val;
                return true;
            }
        }

        bool lower_left_bound(X x, X& res) {//k以下で最大。 
            pushup(root);
            NODE* r = lower_left_bound__(x);
            if(r == nullptr) return false;
            else {
                res = r -> val;
                return true;
            }
        }

        bool upper_left_bound(X x, X& res) {//k未満で最大。
            pushup(root);
            NODE* r = upper_left_bound__(x);
            if(r == nullptr) return false;
            else {
                res = r -> val;
                return true;
            }
        }

        X accL(int R) {//valの、小さい方からRこのモノイド積 Rがkeyの数より多いと単位元 
            if(R < 1 || size_of_tree < R) return X();
            pushup(root);
            X tar;
            if(!ith_element(R, tar)) return X();
            splay(root, tar);
            return acc(root -> lch) + root -> val;
        }

        X accR(int L) {//[L, MAX]のvalのモノイド
            if(L < 1 || size_of_tree < L) return X();
            pushup(root);
            X tar;
            if(!ith_element(L, tar)) return X();
            splay(root, tar);
            return root -> val + acc(root -> rch);
        }

        bool lower_sum_left(X sum, int L, X& res) {
            pushup(root);
            NODE* tar = lower_sum_left__(root, sum, L);
            if(tar == nullptr) return false;
            else {
                res = acc(tar -> lch) + tar -> val;
                return true;
            }

        }

        bool upper_sum_left(X sum, int L, X& res) {
            pushup(root);
            NODE* tar = upper_sum_left__(root, sum, L);
            if(tar == nullptr) return false;
            else {
                res = acc(tar -> lch) + tar -> val;
                //res = count(tar -> lch) + 1;
                return true;
            }

        }

        
        vector<X> in_order() {//要素を全て入れた配列 要素がないなら空配列
            pushup(root);
            vector<X> res;
            in_order__(root, res);
            return res;
        }

        void dump() {
            pushup(root);
            auto r = in_order();
            for(X& x : r) cout << x << " ";
            cout << endl;
        }

        NODE* end() {
            return nullptr;
        }

};

/*
@brief splay_tree(set) トップダウンにsplay
*/
#line 1 "Others/splayset.cpp"

template<typename X>
struct splay_set {
    struct node_t {
            X val;
            X acc;
            int sum = 0;
            node_t* lch;
            node_t* rch;
            node_t(X v):  val(v), acc(v) {
                sum = 1;
                lch = nullptr;
                rch = nullptr;
            }
    };
    using NODE = node_t;
    NODE* root = nullptr;//Splay木の根を表すノード。
    long long size_of_tree = 0;//木に登録されている要素数を返す。
    int pre = 0;
    splay_set(){}

    private:

        long long count(NODE* now) {return now == nullptr ? 0 : now -> sum;}
        X acc(NODE* now) {return !now ? X() : now -> acc;}

        NODE* pushup(NODE* now) {
            if(now != nullptr) {
                now -> sum = count(now -> lch) + count(now -> rch) + 1;
                now -> acc = acc(now -> lch) + now -> val + acc(now -> rch);
            }
            return now;
        }


        NODE* rotate(NODE* now, int b) {//ノードnowを回転させる処理。b = 1で右回転、 b = 0で左回転。」
            if(b==1) {
                NODE* s = now -> lch;
                now -> lch = s -> rch;
                s -> rch = now;
                pushup(now), pushup(s);
                return s;//戻り値は、回転した後nowの位置にくるノードのポインタ。
            }
            else {
                NODE* s = now -> rch;
                now -> rch = s -> lch;
                s -> lch = now;
                pushup(now), pushup(s);
                return s;
            }
        }
        /*

        NODE* splay_sub_pos(NODE* now, int pos, pair<int, NODE*>& history, bool& found) {
            if(now == nullptr) {
                found = false;
                return now;
            } 
            if(count(now -> lch) + 1 == pos) {
                return now;
            }

            int b = 1;
            if(count(now -> lch) + 1 < pos) {
                pos -= count(now -> lch) + 1;
                now -> rch = splay_sub_pos(now -> rch, pos, history, found);
                pushup(now);
            }
            else {
                b = 0, now -> lch = splay_sub_pos(now -> lch, pos, history, found);
                pushup(now);
            } 

            if(!found) return now;

            auto [pb, pn] = history;
            if(pn == nullptr) history = make_pair(b, now);
            else {
                history = make_pair(-1, nullptr);
                if(b == pb) {
                    now = rotate(now, 1 - b);
                    now = rotate(now, 1 - b);
                }
                else {
                    if(b==1) now -> rch = rotate(pn, 1 - pb);
                    else now -> lch = rotate(pn, 1 - pb);
                    pushup(now);
                    now = rotate(now, 1 - b);
                }
            }
            return now;
        }*/

        NODE* splay_sub(NODE* now, const X& x, pair<int, NODE*>& history, bool& found) {
            if(now == nullptr) {
                found = false;
                return now;
            } 
            if(now -> val == x) {
                return now;
            }

            int b = 1;
            if(x > now -> val) {
                now -> rch = splay_sub(now -> rch, x, history, found);
                pushup(now);
            }
            else if(x < now -> val) {
                b = 0, now -> lch = splay_sub(now -> lch, x, history, found);
                pushup(now);
            } 

            if(!found) return now;

            auto [pb, pn] = history;
            if(pn == nullptr) history = make_pair(b, now);
            else {
                history = make_pair(-1, nullptr);
                if(b == pb) {
                    now = rotate(now, 1 - b);
                    now = rotate(now, 1 - b);
                }
                else {
                    if(b==1) now -> rch = rotate(pn, 1 - pb);
                    else now -> lch = rotate(pn, 1 - pb);
                    pushup(now);
                    now = rotate(now, 1 - b);
                }
            }
            return now;
        }

        void splay(NODE* now, const X& x) {
            bool found = true;
            pair<int, NODE*> h(-1, nullptr);
            root = splay_sub(now, x, h, found);
            if(found && h.second != nullptr) {
                root = rotate(root, 1 - h.first);
            }
            return ;
        }
        /*
        void splay_pos(NODE* now, int pos) {
            bool found = true;
            pair<int, NODE*> h(-1, nullptr);
            root = splay_sub_pos(now, pos, h, found);
            if(found && h.second != nullptr) {
                root = rotate(root, 1 - h.first);
            }
            return ;

        }*/
 
 
        NODE* change__(NODE* now, X& x) {//現在見ているノード | 挿入する値
            if(now == nullptr) {
                size_of_tree++;
                return new NODE(x);
            }

            if(now -> val == x) return now;


            if(x > now -> val) {
                now -> rch = change__(now -> rch, x);
                pushup(now);
                return now;
            }
            else {
                now -> lch = change__(now -> lch, x);
                pushup(now);
                return now;
            }
        }

       
        NODE* find_max_only(NODE* now) {//nowを根とする部分木の中で最大の要素を持つノードを返す。この時、splay操作は行わない。
           if(now == nullptr) return now;
           NODE* res = now;
           while(res -> rch != nullptr) res  = res -> rch;
           return res;
        }

        NODE* find_min_only(NODE* now) {//nowを根とする部分木の中で最小の要素を持つノードを返す。この時、splay操作は行わない。
           if(now == nullptr) return now;
           NODE* res = now;
           while(res -> lch != nullptr) res = res -> lch;
           return res;
        }


        NODE* erase__(NODE*now, X& x){//削除ノードまで降っていき、削除が完了次第葉の方から再構成する。
            if(now == nullptr) return now;
            if(x < now -> val) {
                now -> lch = erase__(now -> lch, x);
                pushup(now);
            }
            else if(x > now -> val) {
                now -> rch = erase__(now -> rch, x);
                pushup(now);
            }
            else {
                if(now -> lch == nullptr) {//左に子がない時
                    NODE* tmp = now -> rch;
                    delete now;
                    size_of_tree--;
                    return tmp;
                }
                else if(now -> rch == nullptr) {//右に子がない時
                    NODE* tmp = now -> lch;
                    delete now;
                    size_of_tree--;
                    return tmp;
                } else {//右にも左にも子がある時
                    NODE* tmp = find_max_only(now -> lch);//左子孫の最大値
                    now -> val = tmp -> val;
                    now -> lch = erase__(now -> lch, tmp -> val);//移動したノードを削除。(ポインタの操作に注意)
                    pushup(now);
                }
            }
            return now;//現在のノードまで削除の作業が完了したらば、更新された現在のノードを返して終了。
        }


        void lower_bound_val__(NODE*now, X& x, X& res) {//x以上で最小val
        //前提:その様な値が存在する。
            if(now -> val == x) {
                res = x;
                return;
            }
            if(x < now -> val) {//答えは、min(now, nowの左子孫の中でx以上の最小の要素)
                res = min(res, now -> val);
                if(now -> lch != nullptr) lower_bound_val__(now -> lch, x, res);
            }
            else {//答えは、右子孫の中でx以上の最小の値
                if(now -> rch != nullptr)  lower_bound_val__(now -> rch, x, res);//右に子が存在しないという事はない。
            }
            return;
        }

        void upper_bound_val__(NODE*now, X& x, X& res) {//x超過で最小val
        //前提:その様な値が存在する。
            if(x < now -> val) {//答えは、min(now, nowの左子孫の中でxより大きい最小の要素)
                res = min(res, now -> val);
                if(now -> lch != nullptr) upper_bound_val__(now -> lch, x, res);
            }
            else {//答えは、右子孫の中でxより大きいの最小の値
                if(now -> rch != nullptr)  upper_bound_val__(now -> rch, x, res);//右に子が存在しないという事はない。
            }
            return;
        }
      
      
        void lower_left_bound_val__(NODE* now, X& x, X& res) {//x以下で最大val
        //前提:その様な値が存在する。
            if(now -> val == x) {
                res = x;
                return;
            }
            if(x < now -> val) {//左
                if(now -> lch != nullptr) lower_left_bound_val__(now -> lch, x, res);
            }
            else {
                res = max(res, now -> val);
                if(now -> rch != nullptr) lower_left_bound_val__(now -> rch, x, res);

            }
        }

        void upper_left_bound_val__(NODE* now, X& x, X& res) {//x未満で最大val
        //前提:その様な値が存在する。
            if(x <= now -> val) {//左
                if(now -> lch != nullptr) upper_left_bound_val__(now -> lch, x, res);
            }
            else {
                res = max(res, now -> key);
                if(now -> rch != nullptr) upper_left_bound_val__(now -> rch, x, res);
            }
        }

        NODE* lower_bound__(X x) {//x以上で最小、存在しないならnullptr
            if(size_of_tree==0) return nullptr;
            NODE* M = find_max_only(root);
            X t = M -> val;
            if(t < x) return nullptr;//x以上の値は存在しない。
            lower_bound_val__(root, x, t);
            splay(root, t);
            return root;
        }

        NODE* upper_bound__(X x) {//k超過で最小、存在しないならnullptr
            if(size_of_tree==0) return nullptr;
            NODE* M = find_max_only(root);
            X t = M -> val;
            if(t <= x) return nullptr;
            upper_bound_val__(root, x, t);
            splay(root, t);
            return root;
        }

        NODE* lower_left_bound__(X x) {//k以下で最大。
            if(size_of_tree==0) return nullptr;
            NODE* m = find_min_only(root);
            X t = m -> val;
            if(t > x) return nullptr;
            lower_left_bound_val__(root, x, t);
            splay(root,t);
            return root;
        }

        NODE* upper_left_bound__(X x) {//k未満で最大。
            if(size_of_tree==0) return nullptr;
            NODE* m = find_min_only(root);
            X t = m -> val;
            if(t >= x) return nullptr;
            upper_left_bound_val__(root, x, t);
            splay(root, t);
            return root;
        }

        NODE* ith_element__(NODE* now, long long i) {
            long long ls = count(now -> lch);
            if(ls + 1 <= i && i <= ls + 1) {
                return now;
            }
            else if(ls >= i) return ith_element__(now -> lch, i);
            else return ith_element__(now -> rch, i - 1 - ls);
        }

        NODE* max_element__() {//最大のkey、存在しないならnullptr
            NODE* tar = find_max_only(root);
            if(tar == nullptr) return tar;
            pair<int, NODE*> h (-1, nullptr);
            splay(root , tar -> val);
            return root;
        }

        NODE* min_element__() {//最小のkey、存在しないならnullptr
            NODE* tar = find_min_only(root);
            if(tar == nullptr) return tar;
            pair<int, NODE*> h (-1, nullptr);
            splay(root , tar -> val);
            return root;
        }

        NODE* lower_sum_left__(NODE* now, X S, int L) {
            X now_sum = X();
            if(L != 1) {
                S = S + accL(L-1);
            }
            if(S > acc(root)) return nullptr;
            while(1) {
                X tmp = now_sum + acc(now -> lch);
                if(tmp >= S) now = now -> lch;
                else {
                    tmp += now -> val;
                    if(tmp >= S) {
                        splay(root, now->val);
                        return root;
                    }
                    else {
                        now_sum = tmp;
                        now = now -> rch;
                    }
                }
            }
        }

        NODE* upper_sum_left__(NODE* now, X S, int L) {
            X now_sum = X();
            if(L != 1) {
                S = S + accL(L-1);
            }
            if(S >= acc(root)) return nullptr;
            while(1) {
                X tmp = now_sum + acc(now -> lch);
                if(tmp > S) now = now -> lch;
                else {
                    tmp += now -> val;
                    if(tmp > S) {
                        splay(root, now->val);
                        return root;
                    }
                    else {
                        now_sum = tmp;
                        now = now -> rch;
                    }
                }
            }
        }

        NODE* next(NODE*& now) {//次のkey、存在しないならnullptr
            if(now == nullptr) return now;
            else return upper_bound__(now -> val);
        }


        NODE* prev(NODE*& now) {//前のkey。存在しなければnullptr
            if(now == nullptr) return now;
            else return upper_left_bound__(now -> val);
        }

        void in_order__(NODE* now, vector<X>& res) {
            if(now == nullptr) return;
            in_order__(now -> lch, res);
            res.push_back(now -> val);
            in_order__(now -> rch, res);
            return;
        }



    public:


        void insert(X x) {
            pushup(root);
            change(x);
        }

        void erase(X x) {//存在しなかった場合、何もしない。
            pushup(root);
            root = erase__(root, x);
        }

        bool find(X x) {
            pushup(root);
            splay(root,x);
            if(root == nullptr || root -> val != x) return false;
            return true;
        }

        int count(X x) {
            pushup(root);
            splay(root, x);
            if(root == nullptr || root -> val != x) return 0;
            return 1;
        }


        
        void change(X x) {//xを挿入)
            pushup(root);
            root = change__(root, x);
            splay(root, x);//根を更新。
            return;
        }

  
        int size() {
            return size_of_tree;
        }

        bool empty() {
            return size_of_tree == 0;
        }

        
        bool next(X x, X& res) {//次のkey。存在しないならfalse。結果はresに渡される。
            pushup(root);
            NODE* r = upper_bound__(x);
            if(r==nullptr)return false;
            else {
                res = r -> val;
                return true;
            }
        }

        
        bool prev(X x, X& res) {//前のkey.存在しないならfalse。結果はresに渡される。
            pushup(root);
            NODE* r = upper_left_bound__(x);
            if(r==nullptr)return false;
            else {
                res = r -> val;
                return true;
            }
        }

        bool ith_element(long long i, X& res) {
            pushup(root);
            if(count(root) < i) return false;
            else {
                NODE* tar = ith_element__(root, i);
                res = tar -> val;
                return i;
            }
        }

        long long get_order(X& x) {
            pushup(root);
            splay(root, x);
            if(root == nullptr || root -> val != x) return -1LL;
            else return count(root -> lch) + 1;
        }

        bool max_element(X& res) {//最大のkey
            pushup(root);
            NODE* tar = max_element__();
            if(tar == nullptr) return false;
            else {
                res =  tar -> val;
                return true;
            }
        }

        bool min_element(X& res) {//最小のkey
            pushup(root);
            NODE* tar = min_element__();
            if(tar == nullptr) return false;
            else {
                res =  tar -> val;
                return true;
            }
        }

        bool lower_bound(X x, X& res) {//x以上で最小key
            pushup(root);
            NODE* r = lower_bound__(x);
            if(r == nullptr) return false;
            else {
                res = r -> val;
                return true;
            }
        }

        bool upper_bound(X x, X& res) {//k超過で最小となる
            pushup(root);
            NODE* r = upper_bound__(x);
            if(r == nullptr) return false;
            else {
                res = r -> val;
                return true;
            }
        }

        bool lower_left_bound(X x, X& res) {//k以下で最大。 
            pushup(root);
            NODE* r = lower_left_bound__(x);
            if(r == nullptr) return false;
            else {
                res = r -> val;
                return true;
            }
        }

        bool upper_left_bound(X x, X& res) {//k未満で最大。
            pushup(root);
            NODE* r = upper_left_bound__(x);
            if(r == nullptr) return false;
            else {
                res = r -> val;
                return true;
            }
        }

        X accL(int R) {//valの、小さい方からRこのモノイド積 Rがkeyの数より多いと単位元 
            if(R < 1 || size_of_tree < R) return X();
            pushup(root);
            X tar;
            if(!ith_element(R, tar)) return X();
            splay(root, tar);
            return acc(root -> lch) + root -> val;
        }

        X accR(int L) {//[L, MAX]のvalのモノイド
            if(L < 1 || size_of_tree < L) return X();
            pushup(root);
            X tar;
            if(!ith_element(L, tar)) return X();
            splay(root, tar);
            return root -> val + acc(root -> rch);
        }

        bool lower_sum_left(X sum, int L, X& res) {
            pushup(root);
            NODE* tar = lower_sum_left__(root, sum, L);
            if(tar == nullptr) return false;
            else {
                res = acc(tar -> lch) + tar -> val;
                return true;
            }

        }

        bool upper_sum_left(X sum, int L, X& res) {
            pushup(root);
            NODE* tar = upper_sum_left__(root, sum, L);
            if(tar == nullptr) return false;
            else {
                res = acc(tar -> lch) + tar -> val;
                //res = count(tar -> lch) + 1;
                return true;
            }

        }

        
        vector<X> in_order() {//要素を全て入れた配列 要素がないなら空配列
            pushup(root);
            vector<X> res;
            in_order__(root, res);
            return res;
        }

        void dump() {
            pushup(root);
            auto r = in_order();
            for(X& x : r) cout << x << " ";
            cout << endl;
        }

        NODE* end() {
            return nullptr;
        }

};

/*
@brief splay_tree(set) トップダウンにsplay
*/
Back to top page