平衡树专题

复习一波平衡树!

 

3224: Tyvj 1728 普通平衡树

链接

怎么能少得了这道题呢。

  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 }
View Code

 

2827: 千山鸟飞绝 

链接

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 #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 }
View Code

 

1058: [ZJOI2007]报表统计

链接

前驱后继。set。

 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 }
View Code

 

1251: 序列终结者

链接

维护最大值,区间翻转,被下放标记搞晕了。。

  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 }
View Code

 

1014: [JSOI2008]火星人prefix

链接

求lcp,可以后缀数组+st表,但是这里有修改,所以直接二分+hash,加上平衡树维护hash值。

因为两个错误调了好久!!!

  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 }
View Code

 

posted @ 2018-12-13 22:19  MJT12044  阅读(255)  评论(0编辑  收藏  举报