4825: [Hnoi2017]单旋
4825: [Hnoi2017]单旋
分析:
以后采取更保险的方式写代码!!!81行本来以为不特判也可以,然后就总是比答案大1,甚至出现负数,调啊调啊调啊调~~~
只会旋转最大值和最小值,以最小值为例,画一下图可以看出,旋转后,深度分成三部分讨论,最小值的深度(变为1),最小值右子树的深度(不变),其他的点的深度(整体加1)。所以线段树维护一下。
现在考虑如何插入一个点,可以知道一个点加入后一定是在前驱的右边,或者后继的左边。一个性质:前驱后继一定在splay上是一个是另一个的祖先的关系(反证:若中间存在一个点为它们两个的祖先,那么这个点前驱后继一定有一个是中间的点,没有重复的数字)。那么这个点加入的过程中,一定是加入在前驱后继中比较深的一个点。所以可以直接找到前驱后继,深度大的就是它的父节点。
找到根据splay的性质找到相应的区间,进行区间加减,单点求值。前驱后继可以直接在线段树上二分,或者直接用set。(或者直接splay)
代码:
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<iostream> 5 #include<cmath> 6 #include<cctype> 7 #include<set> 8 #include<queue> 9 #include<vector> 10 #include<map> 11 #define Root 1, tot, 1 12 #define lson l, mid, rt << 1 13 #define rson mid + 1, r, rt << 1 | 1 14 #define Clear(x) ch[x][0] = ch[x][1] = fa[x] = 0 15 using namespace std; 16 typedef long long LL; 17 18 inline int read() { 19 int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1; 20 for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f; 21 } 22 23 const int N = 100005; 24 25 int T[N << 2], tag[N << 2], ch[N][2], fa[N], a[N], disc[N], opt[N], Rt; 26 set<int> s; 27 set<int> :: iterator it; 28 29 void pushdown(int rt) { 30 tag[rt << 1] += tag[rt]; tag[rt << 1 | 1] += tag[rt]; 31 T[rt << 1] += tag[rt], T[rt << 1 | 1] += tag[rt]; 32 tag[rt] = 0; 33 } 34 void update(int l,int r,int rt,int L,int R,int v) { 35 if (L <= l && r <= R) { 36 tag[rt] += v; T[rt] += v; return; 37 } 38 if (tag[rt]) pushdown(rt); 39 int mid = (l + r) >> 1; 40 if (L <= mid) update(lson, L, R, v); 41 if (R > mid) update(rson, L, R, v); 42 } 43 void Change(int l,int r,int rt,int p,int v) { 44 if (l == r) { T[rt] = v, tag[rt] = 0; return ; } 45 if (tag[rt]) pushdown(rt); 46 int mid = (l + r) >> 1; 47 if (p <= mid) Change(lson, p, v); 48 if (p > mid) Change(rson, p, v); 49 } 50 int query(int l,int r,int rt,int p) { 51 if (l == r) return T[rt]; 52 if (tag[rt]) pushdown(rt); 53 int mid = (l + r) >> 1; 54 if (p <= mid) return query(lson, p); 55 if (p > mid) return query(rson, p); 56 } 57 int main() { 58 int n = read(), tot = 0; 59 for (int i = 1; i <= n; ++i) { 60 opt[i] = read(); 61 if (opt[i] == 1) a[i] = read(), disc[++tot] = a[i]; 62 } 63 s.insert(-1e9), s.insert(1e9); 64 sort(disc + 1,disc + tot + 1); 65 for (int i = 1; i <= n; ++i) if (opt[i] == 1) a[i] = lower_bound(disc + 1, disc + tot + 1, a[i]) - disc; 66 67 for (int pre, suc, now, mx, mn, i = 1; i <= n; ++i) { 68 if (opt[i] == 1) { 69 it = s.lower_bound(a[i]); suc = *it; pre = *(--it); now = 1; 70 int d1 = -1, d2 = -1; 71 if (pre != -1e9) d1 = query(Root, pre); 72 if (suc != 1e9) d2 = query(Root, suc); 73 if (d1 > d2) now = d1 + 1, fa[a[i]] = pre, ch[pre][1] = a[i]; 74 if (d1 < d2) now = d2 + 1, fa[a[i]] = suc, ch[suc][0] = a[i]; 75 if (now == 1) Rt = a[i], Clear(Rt); 76 Change(Root, a[i], now); 77 s.insert(a[i]); 78 } 79 else if (opt[i] & 1) { 80 it = s.end(); it --; it --; mx = *it; now = query(Root, mx); 81 if (mx != Rt) { // 注意!!!此处需特判!!!!!!!!!!!!! 82 update(Root, 1, mx - 1, 1); 83 if (fa[mx] + 1 <= mx - 1) { 84 update(Root, fa[mx] + 1, mx - 1, -1); 85 } 86 fa[ch[mx][0]] = fa[mx]; ch[fa[mx]][1] = ch[mx][0]; 87 ch[mx][0] = Rt; fa[Rt] = mx; Rt = mx; fa[mx] = 0; 88 Change(Root, mx, 1); 89 } 90 if (opt[i] == 5) { 91 Rt = ch[mx][0], fa[Rt] = 0; Clear(mx); 92 s.erase(s.find(mx)); 93 update(Root, 1, tot, -1); 94 } 95 } 96 else { 97 it = s.begin(); it ++; mn = *it; now = query(Root, mn); 98 if (mn != Rt) { 99 update(Root, mn + 1, tot, 1); 100 if (mn + 1 <= fa[mn] - 1) { 101 update(Root, mn + 1, fa[mn] - 1, -1); 102 } 103 fa[ch[mn][1]] = fa[mn]; ch[fa[mn]][0] = ch[mn][1]; 104 ch[mn][1] = Rt; fa[Rt] = mn; Rt = mn; fa[mn] = 0; 105 Change(Root, mn, 1); 106 } 107 if (opt[i] == 4) { 108 Rt = ch[mn][1]; fa[Rt] = 0; Clear(mn); 109 s.erase(s.find(mn)); 110 update(Root, 1, tot, -1); 111 } 112 } 113 printf("%d\n",now); 114 } 115 return 0; 116 }