平衡树专题
复习一波平衡树!
3224: Tyvj 1728 普通平衡树
怎么能少得了这道题呢。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<cctype> 3 4 const int N = 1000100; 5 6 int siz[N],ch[N][2],fa[N],cnt[N],data[N]; 7 int Root,tn; 8 9 #define ls ch[p][0] 10 #define rs ch[p][1] 11 12 int son(int x) { 13 return x==ch[fa[x]][1]; 14 } 15 void pushup(int p) { 16 siz[p] = siz[ls] + siz[rs] + cnt[p]; 17 } 18 void rotate(int x) { 19 int y = fa[x],z = fa[y],b = son(x),c = son(y),a = ch[x][!b]; 20 if (z) ch[z][c] = x;else Root = x;fa[x] = z; 21 ch[x][!b] = y;fa[y] = x; 22 ch[y][b] = a;if (a) fa[a] = y; 23 pushup(y),pushup(x); 24 } 25 void splay(int x,int rt) { 26 while (fa[x] != rt) { 27 int y = fa[x],z = fa[y]; 28 if (z==rt) rotate(x); 29 else { 30 if (son(x)==son(y)) rotate(y),rotate(x); 31 else rotate(x),rotate(x); 32 } 33 } 34 } 35 int getrnk(int x) { 36 int p = Root,ans = 0; 37 while (true) { 38 if (!p) return ans + 1; 39 if (x == data[p]) {ans += siz[ls];splay(p,0);return ans+1;} 40 if (x < data[p]) p = ls; 41 else { 42 ans += siz[ls] + cnt[p]; 43 p = rs; 44 } 45 } 46 } 47 int getkth(int k) { 48 int p = Root; 49 while (true) { 50 if (siz[ls] < k && k <= siz[ls] + cnt[p]) return data[p]; 51 if (k <= siz[ls]) p = ls; 52 else { 53 k -= siz[ls] + cnt[p]; 54 p = rs; 55 } 56 } 57 } 58 int Newnode(int pa,int d) { 59 ++tn;siz[tn] = cnt[tn] = 1;ch[tn][1] = ch[tn][0] = 0; 60 data[tn] = d;fa[tn] = pa; 61 return tn; 62 } 63 void Insert(int x) { 64 if (!Root) {Root = Newnode(0,x);return ;} 65 int p = Root,pa = 0; 66 while (true) { 67 if (data[p]==x) { 68 cnt[p] ++;pushup(p);pushup(pa);splay(p,0);return ; // Splay ????????????????? 69 } 70 pa = p; // ??! 71 p = ch[p][x > data[p]]; 72 if (!p) { 73 p = Newnode(pa,x); 74 ch[pa][x > data[pa]] = p; 75 pushup(p),pushup(pa);splay(p,0); 76 break; 77 } 78 } 79 } 80 void Clear(int p) { 81 siz[p] = cnt[p] = ch[p][0] = ch[p][1] = fa[p] = data[p] = 0; 82 } 83 void Delete(int x) { 84 getrnk(x); 85 int &p = Root,tmp; 86 if (cnt[p]) {cnt[p]--;pushup(p);return ;} 87 if (!ls && !rs) {Clear(p);Root = 0;return ;} 88 if (!ls || !rs) {tmp = p;p = ls?ls:rs;fa[p] = 0;Clear(tmp);return ;} 89 int pre = ls; 90 while (ch[pre][1]) pre = ch[pre][1]; 91 tmp = p;p = pre; 92 splay(p,0); 93 ch[p][1] = ch[tmp][1];fa[ch[tmp][1]] = p; 94 Clear(tmp);pushup(p); 95 } 96 int main() { 97 int T,opt,x; 98 scanf("%d",&T); 99 while (T--) { 100 scanf("%d%d",&opt,&x); 101 if (opt==1) Insert(x); 102 else if (opt==2) Delete(x); 103 else if (opt==3) printf("%d\n",getrnk(x)); 104 else if (opt==4) printf("%d\n",getkth(x)); 105 else if (opt==5) printf("%d\n",getkth(getrnk(x)-1)); 106 else printf("%d\n",getkth(getrnk(x+1))); 107 } 108 }
2827: 千山鸟飞绝
splay插入删除,下放标记,注意下放的位置。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 #include<stack> 12 #define pa pair<int,int> 13 #define lc ch[p][0] 14 #define rc ch[p][1] 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 = 300005; 24 const LL M = 1ll << 31; 25 struct Bird{ 26 int tuan, shi, wei, id; 27 Bird() {} 28 Bird(int a,int b,int c,int d) { tuan = a, shi = b, wei = c, id = d; } 29 }T[N], A[N], Now; 30 struct OPT{ 31 int id, x, y; 32 }opt[N]; 33 int ch[N][2], fa[N], siz[N], mx[N], Root[N << 1], Tuan[N], Shi[N], bel[N], st[N]; 34 int Index, RootIndex, NowPos; 35 LL ans[N]; 36 stack<int> sk; 37 map< pa ,int>Rt; 38 39 inline int son(int x) { return ch[fa[x]][1] == x; } 40 inline void pushup(int p) { 41 siz[p] = siz[lc] + siz[rc] + 1; 42 mx[p] = max(T[p].wei, max(mx[lc], mx[rc])); 43 } 44 inline void pushdown(int p) { 45 T[p].tuan = max(T[p].tuan, Tuan[p]), T[p].shi = max(T[p].shi, Shi[p]); 46 if (Tuan[p]) { 47 if (lc) Tuan[lc] = max(Tuan[lc], Tuan[p]); 48 if (rc) Tuan[rc] = max(Tuan[rc], Tuan[p]); 49 } 50 if (Shi[p]) { 51 if (lc) Shi[lc] = max(Shi[lc], Shi[p]); 52 if (rc) Shi[rc] = max(Shi[rc], Shi[p]); 53 } 54 Tuan[p] = 0, Shi[p] = 0; 55 } 56 inline void rotate(int x) { 57 int y = fa[x], z = fa[y], b = son(x), c = son(y), a = ch[x][!b]; 58 if (!z) Root[NowPos] = x; else ch[z][c] = x; fa[x] = z; 59 ch[x][!b] = y; fa[y] = x; 60 ch[y][b] = a; if (a) fa[a] = y; 61 pushup(y); pushup(x); 62 } 63 inline void Splay(int x,int rt) { 64 int top = 0, p = x; 65 while (p) st[++top] = p, p = fa[p]; 66 while (top) pushdown(st[top]), top --; 67 while (fa[x] != rt) { 68 int y = fa[x], z = fa[y]; 69 if (z == rt) rotate(x); 70 else { 71 if (son(x) == son(y)) rotate(y), rotate(x); 72 else rotate(x), rotate(x); 73 } 74 } 75 } 76 void getpos(int p,int k) { 77 while (true) { 78 if (k == T[p].id) { Splay(p, 0); Now = T[p]; return ;} // Now找到的需要删除的点,保存下来,再插入到另一棵splay中,注意要先下放完标记!!! 79 if (k < T[p].id) p = lc; 80 else p = rc; 81 } 82 } 83 inline int NewNode(int f,const Bird &A) { 84 int p = sk.size() ? sk.top() : ++Index; 85 T[p] = A, fa[p] = f; ch[p][0] = ch[p][1] = 0; siz[p] = 1, mx[p] = A.wei; 86 return p; 87 } 88 void Insert(int &Root,Bird A) { 89 if (!Root) { Root = NewNode(0, A); return ; } 90 int p = Root, pre = 0; 91 while (true) { 92 pushdown(p); 93 pre = p; p = ch[p][A.id > T[p].id]; 94 if (!p) { 95 p = NewNode(pre, A); // 此处应有下方标记!!! 96 ch[pre][A.id > T[pre].id] = p; 97 pushup(p); pushup(pre); 98 Splay(p, 0); break; 99 } 100 } 101 } 102 inline void Clear(int p) { 103 siz[p] = ch[p][0] = ch[0][1] = fa[p] = mx[p] = Tuan[p] = Shi[p] = 0; sk.push(p); 104 } 105 void Delete(int &Root,int k) { // 在以Root为根的splay中删除标号为k的点 106 getpos(Root, k); 107 int &p = Root, tmp; 108 if (!lc && !rc) { Clear(p); p = 0; return ; } 109 if (!lc || !rc) { tmp = p; p = lc ? lc : rc; fa[p] = 0; Clear(tmp); return ; } 110 int pre = lc; while (ch[pre][1]) pre = ch[pre][1]; 111 tmp = p; p = pre; 112 Splay(p, 0); 113 ch[p][1] = ch[tmp][1], fa[ch[tmp][1]] = p; 114 Clear(tmp); pushup(p); 115 } 116 void dfs(int p) { 117 pushdown(p); 118 ans[T[p].id] = 1ll * T[p].tuan * T[p].shi; 119 if (lc) dfs(lc); 120 if (rc) dfs(rc); 121 } 122 void de(int x) { 123 cout << x << " : \n"; 124 cout << "pos : " << bel[x] << "\n"; 125 cout << "siz : " << siz[Root[bel[x]]] << "\n"; 126 dfs(Root[bel[x]]); 127 cout << "birds : \n"; 128 for (int i = 1; i <= 20; ++i) 129 if (bel[T[i].id] == bel[x]) 130 cout << T[i].id << " " << T[i].wei << " " << T[i].shi << " " << T[i].tuan << "\n"; 131 puts("--------"); 132 } 133 int main() { 134 int n = read(); 135 for (int i = 1; i <= n; ++i) { 136 int w = read(), x = read(), y = read(), tmp = Rt[pa(x, y)], R; 137 if (!tmp) tmp = ++RootIndex, Rt[pa(x, y)] = tmp; 138 A[i] = Bird(0, 0, w, i); 139 140 NowPos = tmp; R = Root[tmp]; 141 if (R) { 142 Shi[R] = max(Shi[R], A[i].wei), Tuan[R] = max(Tuan[R], siz[R]); 143 A[i].shi = max(A[i].shi, mx[R]), A[i].tuan = max(A[i].tuan, siz[R]); 144 } 145 146 Insert(Root[tmp], A[i]); 147 bel[i] = tmp; 148 } 149 int Q = read(); 150 while (Q--) { 151 int v = read(), x = read(), y = read(), tmp = Rt[pa(x, y)], R; 152 if (!tmp) tmp = ++RootIndex, Rt[pa(x, y)] = tmp; // tmp这个位置离散后的标号 153 NowPos = bel[v]; Delete(Root[bel[v]], v); // Root 154 155 NowPos = tmp; R = Root[tmp]; 156 if (R) { 157 Shi[R] = max(Shi[R], Now.wei), Tuan[R] = max(Tuan[R], siz[R]); 158 Now.shi = max(Now.shi, mx[R]), Now.tuan = max(Now.tuan, siz[R]); 159 } 160 161 Insert(Root[tmp], Now); 162 bel[v] = tmp; 163 // de(v); 164 } 165 for (int i = 1; i <= n; ++i) 166 if (Root[bel[i]]) dfs(Root[bel[i]]), Root[bel[i]] = 0; 167 for (int i = 1; i <= n; ++i) printf("%lld\n", ans[i]); 168 return 0; 169 }
1058: [ZJOI2007]报表统计
前驱后继。set。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 using namespace std; 12 typedef long long LL; 13 14 inline int read() { 15 int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1; 16 for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f; 17 } 18 19 const int N = 500005; 20 multiset<int> s; 21 set<int> t; 22 int st[N], ed[N], Min = 2e9; 23 24 void insT(int x) { 25 set<int> :: iterator it = t.lower_bound(x); 26 int t1 = (*it) - x, t2 = x - *(--it); 27 Min = min(Min, min(t1, t2)); 28 t.insert(x); 29 } 30 31 int main() { 32 int n = read(), m = read(); 33 t.insert(-1e9), t.insert(1e9); 34 for (int i = 1; i <= n; ++i) { 35 int x = read(); 36 st[i] = ed[i] = x; 37 insT(x); 38 if (i >= 2) s.insert(abs(st[i] - ed[i - 1])); 39 } 40 char opt[20]; 41 while (m --) { 42 scanf("%s", opt); 43 if (opt[0] == 'I') { 44 int p = read(), x = read(); 45 if (p != n) { 46 s.erase(s.find(abs(st[p + 1] - ed[p]))); 47 s.insert(abs(st[p + 1] - x)); 48 } 49 s.insert(abs(x - ed[p])); 50 ed[p] = x; 51 insT(x); 52 } 53 else if (opt[4] == 'S') printf("%d\n", Min); 54 else printf("%d\n", *s.begin()); 55 } 56 return 0; 57 }
1251: 序列终结者
维护最大值,区间翻转,被下放标记搞晕了。。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 lc ch[p][0] 12 #define rc ch[p][1] 13 using namespace std; 14 typedef long long LL; 15 16 inline int read() { 17 int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1; 18 for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f; 19 } 20 21 const int N = 50005; 22 int rev[N], ch[N][2], fa[N], siz[N], st[N], Root; 23 LL T[N], mx[N], tag[N]; 24 25 inline int son(int x) { return ch[fa[x]][1] == x; } 26 inline void pushup(int p) { 27 siz[p] = siz[lc] + siz[rc] + 1; 28 mx[p] = max(T[p], max(mx[lc], mx[rc])); 29 } 30 inline void pushdown(int p) { 31 if (rev[p]) swap(lc, rc), rev[lc] ^= 1, rev[rc] ^= 1, rev[p] ^= 1; 32 if (tag[p]) { 33 T[p] += tag[p]; 34 mx[lc] += tag[p], mx[rc] += tag[p]; 35 tag[lc] += tag[p], tag[rc] += tag[p]; 36 tag[p] = 0; 37 } 38 } 39 inline void rotate(int x) { 40 int y = fa[x], z = fa[y], b = son(x), c = son(y), a = ch[x][!b]; 41 if (!z) Root = x; else ch[z][c] = x; fa[x] = z; 42 ch[x][!b] = y; fa[y] = x; 43 ch[y][b] = a; if (a) fa[a] = y; 44 pushup(y); pushup(x); 45 } 46 inline void splay(int x,int rt) { 47 while (fa[x] != rt) { 48 int y = fa[x], z = fa[y]; 49 if (z == rt) rotate(x); 50 else { 51 if (son(x) == son(y)) rotate(y), rotate(x); 52 else rotate(x), rotate(x); 53 } 54 } 55 } 56 int build(int l,int r) { 57 if (l > r) return 0; 58 int mid = (l + r) >> 1, tmp; 59 tmp = build(l, mid - 1); 60 if (tmp) fa[tmp] = mid, ch[mid][0] = tmp; 61 tmp = build(mid + 1, r); 62 if (tmp) fa[tmp] = mid, ch[mid][1] = tmp; 63 pushup(mid); 64 return mid; 65 } 66 int getkth(int k) { 67 int p = Root; 68 while (true) { 69 pushdown(p); 70 if (k == siz[lc] + 1) return p; 71 if (k <= siz[lc]) p = lc; 72 else k -= siz[lc] + 1, p = rc; 73 } 74 } 75 void Add(int l,int r,LL x) { 76 l --, r ++; 77 l = getkth(l), r = getkth(r); 78 splay(l, 0); splay(r, l); 79 tag[ch[ch[Root][1]][0]] += x; 80 mx[ch[ch[Root][1]][0]] += x; 81 } 82 void Reverse(int l,int r) { 83 l --, r ++; 84 l = getkth(l), r = getkth(r); 85 splay(l, 0); splay(r, l); 86 rev[ch[ch[Root][1]][0]] ^= 1; 87 } 88 LL query(int l,int r) { 89 l --, r ++; 90 l = getkth(l), r = getkth(r); 91 splay(l, 0); splay(r, l); 92 return mx[ch[ch[Root][1]][0]]; 93 } 94 int main() { 95 int n = read(), m = read(); 96 T[1] = -1e18, T[n + 2] = -1e18; mx[0] = -1e18; 97 Root = build(1, n + 2); 98 while (m --) { 99 int opt = read(), l = read() + 1, r = read() + 1; 100 if (opt == 1) Add(l, r, read()); 101 else if (opt == 2) Reverse(l, r); 102 else printf("%lld\n", query(l, r)); 103 } 104 return 0; 105 }
1014: [JSOI2008]火星人prefix
求lcp,可以后缀数组+st表,但是这里有修改,所以直接二分+hash,加上平衡树维护hash值。
因为两个错误调了好久!!!
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 lc ch[p][0] 12 #define rc ch[p][1] 13 using namespace std; 14 typedef long long LL; 15 typedef unsigned long long uLL; 16 17 inline int read() { 18 int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1; 19 for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f; 20 } 21 22 const int N = 100005; 23 const uLL B = 31; 24 int ch[N][2], siz[N], fa[N], Index, Root, n; 25 uLL ha[N], mi[N], T[N]; 26 char s[N]; 27 28 inline int son(int x) { return ch[fa[x]][1] == x; } 29 inline void pushup(int p) { 30 siz[p] = siz[lc] + siz[rc] + 1; 31 ha[p] = ha[lc] * mi[siz[rc] + 1] + T[p] * mi[siz[rc]] + ha[rc]; 32 } 33 inline void rotate(int x) { 34 int y = fa[x], z = fa[y], b = son(x), c = son(y), a = ch[x][!b]; 35 if (z) ch[z][c] = x; else Root = x; fa[x] = z; 36 ch[x][!b] = y; fa[y] = x; 37 ch[y][b] = a; if (a) fa[a] = y; 38 pushup(y); pushup(x); 39 } 40 inline void splay(int x,int rt) { 41 while (fa[x] != rt) { 42 int y = fa[x], z = fa[y]; 43 if (z == rt) rotate(x); 44 else { 45 if (son(x) == son(y)) rotate(y), rotate(x); 46 else rotate(x), rotate(x); 47 } 48 } 49 } 50 int build(int l,int r) { 51 if (l > r) return 0; 52 int mid = (l + r) >> 1, tmp; 53 tmp = build(l, mid - 1); 54 if (tmp) fa[tmp] = mid, ch[mid][0] = tmp; 55 tmp = build(mid + 1, r); 56 if (tmp) fa[tmp] = mid, ch[mid][1] = tmp; 57 pushup(mid); 58 return mid; 59 } 60 inline int getpos(int k) { 61 int p = Root; 62 while (true) { 63 if (k == siz[lc] + 1) return p; 64 if (k <= siz[lc]) p = lc; 65 else k -= siz[lc] + 1, p = rc; 66 } 67 } 68 uLL getha(int l,int r) { 69 l --, r ++; 70 l = getpos(l), r = getpos(r); 71 splay(l, 0); splay(r, l); 72 return ha[ch[ch[Root][1]][0]]; 73 } 74 inline void Insert(int p,int x) { 75 int l = p, r = p + 1; 76 l = getpos(l), r = getpos(r); 77 splay(l, 0); splay(r, l); 78 int t = ch[Root][1]; 79 ch[t][0] = ++Index, fa[Index] = t, siz[Index] = 1, T[Index] = x, ha[Index] = x; 80 pushup(t); pushup(Root); 81 } 82 inline void Change(int p,int x) { 83 p = getpos(p); 84 splay(p, 0); 85 T[Root] = x; 86 pushup(Root); 87 } 88 inline int query(int a,int b) { 89 if (a > b) swap(a, b); // !!!!!!!!!!!a不一定小于b!!!!!!!!!!!!!! 90 int l = 1, r = Index - b, res = 0; // r的最大值是Index-b!!!not n+2-b 91 while (l <= r) { 92 int mid = (l + r) >> 1; 93 if (getha(a, a + mid - 1) == getha(b, b + mid - 1)) res = mid, l = mid + 1; 94 else r = mid - 1; 95 } 96 return res; 97 } 98 void dfs(int p) { 99 if (lc) dfs(lc); 100 printf("%c",(int)T[p] + 'a' - 1); 101 if (rc) dfs(rc); 102 } 103 int main() { 104 scanf("%s", s + 1); 105 106 n = strlen(s + 1); 107 for (int i = 1; i <= n; ++i) T[i + 1] = s[i] - 'a' + 1; 108 Index = n + 2; mi[0] = 1; 109 for (int i = 1; i <= 100001; ++i) mi[i] = mi[i - 1] * B; 110 Root = build(1, n + 2); 111 112 int m = read(); char opt[10], ch[10]; 113 while (m --) { 114 scanf("%s", opt); 115 if (opt[0] == 'Q') { 116 int l = read() + 1, r = read() + 1; 117 printf("%d\n", query(l, r)); 118 } else if (opt[0] == 'R') { 119 int p = read() + 1; scanf("%s", ch); 120 Change(p, ch[0] - 'a' + 1); 121 } else { 122 int p = read() + 1; scanf("%s", ch); 123 Insert(p, ch[0] - 'a' + 1); 124 } 125 } 126 return 0; 127 }