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
",now);
114     }
115     return 0;
116 }
原文地址:https://www.cnblogs.com/mjtcn/p/10116828.html