[BZOJ 3196] 二逼平衡树

[题目链接]

          https://www.lydsy.com/JudgeOnline/problem.php?id=3196

[算法]

        树套树即可

        笔者的这份代码使用的是线段树套伸展树

        时间复杂度 : O(NlogN ^ 3)

[代码]

         

#include<bits/stdc++.h>
using namespace std;
#define MAXN 50010
#define MAXP 2000005
#define rint register int
#pragma GCC optimize(2)
const int inf = 2147483647;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;

int n , m , rt = 0 , tot = 0 , sz = 0;
int val[MAXN];

struct Snode
{
        int father , son[2];
        int value , cnt , sz;
} a[MAXP];
struct Splay
{
        int rt[MAXP];
        stack< int > S;
        inline int get(int x)
        {
                return a[a[x].father].son[1] == x;
        }
        inline void update(int x)
        {
                a[x].sz = a[x].cnt;
                if (a[x].son[0]) a[x].sz += a[a[x].son[0]].sz;
                if (a[x].son[1]) a[x].sz += a[a[x].son[1]].sz;
        }
        inline void rotate(int x)
        {
                int f = a[x].father , g = a[f].father;
                int tmpx = get(x) , tmpf = get(f);
                int w = a[x].son[tmpx ^ 1];
                if (!f) return;
                if (g) a[g].son[tmpf] = x;
                a[x].son[tmpx ^ 1] = f;
                a[f].son[tmpx] = w;
                if (w) a[w].father = f;
                a[f].father = x;
                a[x].father = g;
                update(f);
        }
        inline void splay(int k , int x)
        {
                for (int f = a[x].father; (f = a[x].father); rotate(x))
                        rotate(get(f) == get(x) ? f : x);
                rt[k] = x;
        }    
        inline int find(int root , int x)
        {
                int now = rt[root];
                while (now > 0)
                {
                        if (a[now].value == x)
                        {
                                splay(root , now);
                                return now;
                        }
                        int tmp = a[now].value < x;
                        if (a[now].son[tmp]) now = a[now].son[tmp];
                        else return 0;
                }
                return 0;
        }
        inline int _insert(int root , int x)
        {
                if (!rt[root])
                {
                        int index = 0;
                        if (!S.empty())
                        {
                            index = S.top();
                            S.pop();
                        } else index = ++sz;
                        a[index].cnt = a[index].sz = 1;
                        a[index].value = x;
                        a[index].son[0] = a[index].son[1] = 0;
                        a[index].father = 0;
                        rt[root] = index;
                        return index; 
                }
                int now = rt[root];
                while (now > 0)
                {
                        if (a[now].value == x)
                        {
                                ++a[now].cnt;
                                splay(root , now);
                                return now;
                        }
                        int tmp = a[now].value < x;
                        if (a[now].son[tmp]) now = a[now].son[tmp];
                        else
                        {
                                int index = 0;
                                if (!S.empty())
                                {
                                    index = S.top();
                                    S.pop();
                                } else index = ++sz;                     
                                a[now].son[tmp] = index;
                                a[index].father = now;
                                a[index].value = x;
                                a[index].sz = a[index].cnt = 1;
                                a[index].son[0] = a[index].son[1] = 0;
                                splay(root , index);
                                return index;
                        }
                }
                return -1;
        }
        inline void join(int root , int u , int v)
        {
                int now = u;
                while (a[now].son[1]) now = a[now].son[1];
                splay(root , now);
                a[now].son[1] = v;
                a[v].father = now;
        }
        inline void erase(int root , int x)
        {
                int id = find(root , x);
                if (!id) return;
                splay(root , id);
                --a[id].cnt;
                if (a[id].cnt > 0) return;
                S.push(id);
                if (!a[id].son[0] && !a[id].son[1])
                {
                        rt[root] = 0;
                        return;
                }
                if (!a[id].son[0])
                {
                        rt[root] = a[id].son[1];
                        a[rt[root]].father = 0;
                        return;
                }
                if (!a[id].son[1])
                {
                        rt[root] = a[id].son[0];
                        a[rt[root]].father = 0;
                        return;
                }
                join(root , a[id].son[0] , a[id].son[1]);
        }
        inline int query_pre(int root , int x)
        {
                int id = find(root , x);
                bool flg = false;
                if (!id) 
                {
                        id = _insert(root , x);
                        flg = true;
                }
                splay(root , id);
                int ret;
                if (!a[id].son[0])
                {
                    ret = -inf;
                } else
                {
                    id = a[id].son[0];
                    while (a[id].son[1]) id = a[id].son[1];
                    ret = a[id].value;
                }
                if (flg) erase(root , x);
                return ret;
        }
        inline int query_suc(int root , int x)
        {
                int id = find(root , x);
                bool flg = false;
                if (!id) 
                {
                        id = _insert(root , x);
                        flg = true;
                }
                splay(root , id);
                int ret;
                if (!a[id].son[1])
                {
                    ret = inf;
                } else
                {    
                    id = a[id].son[1];
                       while (a[id].son[0]) id = a[id].son[0];
                       ret = a[id].value;
                   }
                if (flg) erase(root , x);
                return ret;
        }
        inline int query_s(int root , int x)
        {
                int id = find(root , x);
                bool flg = false;
                if (!id) 
                {
                        id = _insert(root , x);
                        flg = true;
                }
                splay(root , id);
                int ret = a[a[id].son[0]].sz;
                if (flg) erase(root , x);
                return ret;
        }
} T;
struct Segment_Tree
{
        int ls[MAXN << 2] , rs[MAXN << 2];
        Segment_Tree()
        {
                memset(ls , 0 , sizeof(ls));
                memset(rs , 0 , sizeof(rs));
        }
        inline void insert(int &k , int l , int r , int pos , int value)
        {
                if (!k) k = ++tot;
                T._insert(k , value);
                if (l == r) return;
                int mid = (l + r) >> 1;
                if (mid >= pos) insert(ls[k] , l , mid , pos , value);
                else insert(rs[k] , mid + 1 , r , pos , value);    
        }        
        inline int query_s(int k , int l , int r , int ql , int qr , int value)
        {
                if (l == ql && r == qr)
                        return T.query_s(k , value);
                int mid = (l + r) >> 1;
                if (mid >= qr) return query_s(ls[k] , l , mid , ql , qr , value);
                else if (mid + 1 <= ql) return query_s(rs[k] , mid + 1 , r , ql , qr , value);
                else return query_s(ls[k] , l , mid , ql , mid , value) + query_s(rs[k] , mid + 1 , r , mid + 1 , qr , value);
        }
        inline void modify(int k , int l , int r , int pos , pair<int , int> val)
        {
                T.erase(k , val.first);
                T._insert(k , val.second);
                if (l == r) return;
                int mid = (l + r) >> 1;
                if (mid >= pos) modify(ls[k] , l , mid , pos , val);
                else modify(rs[k] , mid + 1  , r , pos , val);
        }
        inline int query_pre(int k , int l , int r , int ql , int qr , int value)
        {
                if (l == ql && r == qr)
                        return T.query_pre(k , value);
                int mid = (l + r) >> 1;
                if (mid >= qr) return query_pre(ls[k] , l , mid , ql , qr , value);
                else if (mid + 1 <= ql) return query_pre(rs[k] , mid + 1 , r , ql , qr , value);
                else return max(query_pre(ls[k] , l , mid , ql , mid , value) , query_pre(rs[k] , mid + 1 , r , mid + 1 , qr , value));        
        } 
        inline int query_suc(int k , int l , int r , int ql , int qr , int value)
        {    
                if (l == ql && r == qr)
                        return T.query_suc(k , value);
                int mid = (l + r) >> 1;
                if (mid >= qr) return query_suc(ls[k] , l , mid , ql , qr , value);
                else if (mid + 1 <= ql) return query_suc(rs[k] , mid + 1 , r , ql , qr , value);
                else return min(query_suc(ls[k] , l , mid , ql , mid , value) , query_suc(rs[k] , mid + 1 , r , mid + 1 , qr , value));
        }
} SGT;

template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); }
template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); }
template <typename T> inline void read(T &x)
{
    T f = 1; x = 0;
    char c = getchar();
    for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
    for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
    x *= f;
}

int main()
{
        

        read(n); read(m);
        for (rint i = 1; i <= n; i++) read(val[i]);
        for (rint i = 1; i <= n; i++) SGT.insert(rt , 1 , n , i , val[i]);
        for (rint i = 1; i <= m; i++)
        {
                int type;
                read(type);
                if (type == 1)
                {
                        int l , r , k;
                        read(l); read(r); read(k);
                        printf("%d\n" , SGT.query_s(rt , 1 , n , l , r , k) + 1);
                } 
                if (type == 2)
                {
                        int l , r , k;
                        read(l); read(r); read(k);
                        int lft = 0 , rgt = (int)1e8 , ans = 0;
                        while (lft <= rgt)
                        {
                                int mid = (lft + rgt) >> 1;
                                if (SGT.query_s(rt , 1 , n , l , r , mid) + 1 <= k)
                                {
                                        ans = mid;
                                        lft = mid + 1;
                                } else rgt = mid - 1;
                        }
                        printf("%d\n" , ans);
                }
                if (type == 3)
                {
                        int pos , k;
                        read(pos); read(k);
                        SGT.modify(rt , 1 , n , pos , make_pair(val[pos] , k));
                        val[pos] = k;
                }
                if (type == 4)
                {
                        int l , r , k;
                        read(l); read(r); read(k);
                        printf("%d\n" , SGT.query_pre(rt , 1 , n , l , r , k));
                } 
                if (type == 5)
                {
                        int l , r , k;
                        read(l); read(r); read(k);
                        printf("%d\n" , SGT.query_suc(rt , 1 , n , l , r , k));
                }
        }
        
        return 0;
    
}

 

posted @ 2018-12-27 21:56  evenbao  阅读(185)  评论(0编辑  收藏  举报