[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; }