日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[HNOI2017]单旋

發布時間:2023/12/20 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [HNOI2017]单旋 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題意:

模擬一棵單旋splay,支持五種操作

\(\text{Solution:}\)

顯然不是讓你碼一顆單旋splay(一條鏈卡爆你)。

在草稿紙上畫一畫,模擬一遍,觀察中序遍歷下的深度變化,發現當x為最小值時它沒有左兒子,可能有右兒子,splay到根后除了它的右兒子深度不變,其余的深度都+1,x為最大值時同理。

因此,每次操作我們都可以用線段樹直接維護深度,接下來要解決的問題就是怎么插入。

二叉搜索樹一個點總是插在其前驅的右兒子或是后繼的左兒子

所以我們只要找到它前驅或后繼,然后接在它的下面,這個過程很容易用set實現,還要記錄每個點的左兒子以及右兒子是誰,不然無法判斷插入到前驅和后繼哪個下面去。

\(\text{Source}\)

// luogu-judger-enable-o2 #include <set> #include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <assert.h> #include <algorithm>using namespace std;#define LL long long #define debug(...) fprintf(stderr, __VA_ARGS__) #define GO debug("GO\n")inline int rint() {register int x = 0, f = 1; register char c;while (!isdigit(c = getchar())) if (c == '-') f = -1;while (x = (x << 1) + (x << 3) + (c ^ 48), isdigit(c = getchar()));return x * f; }template<typename T> inline void chkmin(T &a, T b) { a > b ? a = b : 0; } template<typename T> inline void chkmax(T &a, T b) { a < b ? a = b : 0; }const int N = 1e5 + 10;#define Iter set<int>::iterator set<int> S; int a[N], tot, ch[N][2], fa[N], m, op[N], buc[N], root; int dep[N<<2];void add(int x, int l, int r, int L, int R, int val) {if (L <= l and r <= R) {dep[x] += val;return;}int mid = (l + r) >> 1;if (L <= mid) add(x<<1, l, mid, L, R, val);if (mid < R) add(x<<1|1, mid + 1, r, L, R, val); }int query(int x, int l, int r, int p) {if (l == r) {return dep[x];}int mid = (l + r) >> 1;if (p <= mid) return dep[x] + query(x<<1, l, mid, p);else return dep[x] + query(x<<1|1, mid+1, r, p); }void change(int x, int y) {add(1, 1, tot, x, x, y - query(1, 1, tot, x)); }int Insert(int x) {Iter it = S.insert(x).first;if (root == 0) {root = x;change(x, 1);return 1;}if (it != S.begin()) {if (ch[*--it][1] == 0) ch[fa[x] = *it][1] = x;it++;}if (fa[x] == 0) ch[fa[x] = *++it][0] = x;int res = query(1, 1, tot, fa[x]) + 1;change(x, res);return res; }int findmin() {int x = *S.begin(), res = query(1, 1, tot, x);if (x == root) return 1;if (x + 1 <= fa[x] - 1)add(1, 1, tot, x + 1, fa[x] - 1, -1);add(1, 1, tot, 1, tot, 1);ch[fa[x]][0] = ch[x][1], fa[ch[x][1]] = fa[x];fa[root] = x, ch[x][1] = root;root = x;change(x, 1);return res; }int findmax() {int x = *S.rbegin(), res = query(1, 1, tot, x);if (x == root) return 1;if (x - 1 >= fa[x] + 1)add(1, 1, tot, fa[x] + 1, x - 1, -1);add(1, 1, tot, 1, tot, 1);ch[fa[x]][1] = ch[x][0], fa[ch[x][0]] = fa[x];fa[root] = x, ch[x][0] = root;root = x;change(x, 1);return res; }void delmin() {printf("%d\n", findmin());add(1, 1, tot, 1, tot, -1);S.erase(root);root = ch[root][1];fa[root] = 0; }void delmax() {printf("%d\n", findmax());add(1, 1, tot, 1, tot, -1);S.erase(root);root = ch[root][0];fa[root] = 0; }int main() { #ifndef ONLINE_JUDGEfreopen("xhc.in", "r", stdin);freopen("xhc.out", "w", stdout); #endifm = rint();for (int i = 1; i <= m; ++ i) {op[i] = rint();if (op[i] == 1) {tot++;a[tot] = buc[tot] = rint();}}sort(buc + 1, buc + 1 + tot);for (int i = 1; i <= tot; ++ i)a[i] = lower_bound(buc + 1, buc + 1 + tot, a[i]) - buc;for (int i = 1, cnt = 0; i <= m; ++ i) {switch(op[i]) {case 1: printf("%d\n", Insert(a[++cnt])); break;case 2: printf("%d\n", findmin()); break;case 3: printf("%d\n", findmax()); break;case 4: delmin(); break;case 5: delmax(); break;}} }

轉載于:https://www.cnblogs.com/cnyali-Tea/p/10594663.html

總結

以上是生活随笔為你收集整理的[HNOI2017]单旋的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。