平衡树学习总结、LCT练习题

Splay:

  像BST(二叉搜索树)一样插入查询,可以改变树的形状,可以区间翻转,可以实现动态树,不可持久化。

核心代码:

 1 void rotate(int a) // 旋转
 2 {
 3     int b = fa[a], c = fa[b];
 4     int k = son[b][1] == a, w = son[a][!k];
 5 
 6     if (no_root(b)) son[c][son[c][1] == b] = a;
 7     son[a][!k] = b;
 8     son[b][k] = w;
 9 
10     if (w) fa[w] = b;
11     fa[b] = a;
12     fa[a] = c;
13     pushup(b);
14 }
15 
16 void splay(int x) // 将x移动到splay的根
17 {
18     int y = x, z = 0;
19     stk[++z] = y;
20 
21     while (no_root(y)) stk[++z] = y = fa[y];
22     while (z) pushdown(stk[z--]);
23 
24     while (no_root(x))
25     {
26         y = fa[x]; z = fa[y];
27         if (no_root(y)) rotate((son[y][0] == x) ^ (son[z][0] == y) ? x : y);
28         rotate(x);
29     }
30     pushup(x);
31 }
View Code

 

Treap:

 

  具有堆性质的BST,每个点有两个关键字,一个key为原来BST维护的值,一个fix

值,一个节点新建时,给予它一个随机的fix值,以fix为关键字构成最小根,Treap的期望高度为O(log  n)。

 

【模板】普通平衡树(题目):

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<iostream>
  4 #include<algorithm>
  5 using namespace std;
  6 
  7 const int N = 2000010, INF = 1e9 + 7;
  8 
  9 int root;
 10 
 11 struct Node
 12 {
 13     int l, r, val, size, dat, cnt;
 14     Node() {}
 15     Node(int l, int r, int val, int size, int cnt) :l(l), r(r), val(val), size(size), cnt(cnt) {}
 16 };
 17 
 18 int cnt;
 19 Node tr[N];
 20 
 21 int New(int x)
 22 {
 23     tr[++cnt] = Node(0, 0, x, 1, 1);
 24     tr[cnt].dat = rand();
 25     return cnt;
 26 }
 27 
 28 void update(int q)
 29 {
 30     tr[q].size = tr[tr[q].l].size + tr[q].cnt + tr[tr[q].r].size;
 31 }
 32 
 33 void build()
 34 {
 35     New(-INF), New(INF);
 36     root = 1;
 37     tr[1].r = 2;
 38     update(root);
 39 }
 40 
 41 void zig(int &q) // 右旋
 42 {
 43     int p = tr[q].l;
 44     tr[q].l = tr[p].r;
 45     tr[p].r = q;
 46     q = p;
 47 
 48     update(tr[q].r);
 49     update(q);
 50 }
 51 
 52 void zag(int& q)
 53 {
 54     int p = tr[q].r;
 55     tr[q].r = tr[p].l;
 56     tr[p].l = q;
 57     q = p;
 58 
 59     update(tr[q].l);
 60     update(q);
 61 }
 62 
 63 
 64 void insert(int& q, int x)
 65 {
 66     if (!q)
 67     {
 68         q = New(x);
 69         return;
 70     }
 71 
 72     if (x == tr[q].val)
 73     {
 74         tr[q].cnt++;
 75         update(q);
 76         return;
 77     }
 78 
 79     if (x < tr[q].val)
 80     {
 81         insert(tr[q].l, x);
 82         if (tr[q].dat < tr[tr[q].l].dat) zig(q);
 83     }
 84     else
 85     {
 86         insert(tr[q].r, x);
 87         if (tr[q].dat < tr[tr[q].r].dat) zag(q);
 88     }
 89     update(q);
 90 }
 91 
 92 void Delete(int &q, int x)
 93 {
 94     if (!q) return;
 95     if (x == tr[q].val)
 96     {
 97         if (tr[q].cnt > 1)
 98         {
 99             tr[q].cnt--;
100             update(q);
101             return;
102         }
103         if (tr[q].l || tr[q].r)
104         {
105             if (tr[q].r == 0 || tr[tr[q].l].dat > tr[tr[q].r].dat) zig(q), Delete(tr[q].r, x);
106             else zag(q), Delete(tr[q].l, x);
107             update(q);
108         }
109         else q = 0;
110         return;
111     }
112 
113     if (x < tr[q].val) Delete(tr[q].l, x);
114     else Delete(tr[q].r, x);
115     update(q);
116 }
117 
118 int find_rank(int q, int x)
119 {
120     if (!q) return 0;
121     if (x == tr[q].val) return tr[tr[q].l].size + 1;
122     if (x < tr[q].val) return find_rank(tr[q].l, x);
123     else return find_rank(tr[q].r, x) + tr[q].cnt + tr[tr[q].l].size;
124 }
125 
126 int find_num(int q, int x)
127 {
128     if (!q) return INF;
129     if (x <= tr[tr[q].l].size) return find_num(tr[q].l, x);
130     if (x <= tr[tr[q].l].size + tr[q].cnt) return tr[q].val;
131     return find_num(tr[q].r, x - tr[tr[q].l].size - tr[q].cnt);
132 }
133 
134 int find_befor(int x)
135 {
136     int ans = 1, q = root;
137     while (q)
138     {
139         if (x == tr[q].val)
140         {
141             if (tr[q].l > 0)
142             {
143                 q = tr[q].l;
144                 while (tr[q].r > 0) q = tr[q].r;
145                 ans = q;
146             }
147             break;
148         }
149         if (tr[q].val<x && tr[q].val>tr[ans].val) ans = q;
150         if (x < tr[q].val) q = tr[q].l;
151         else q = tr[q].r;
152     }
153     return tr[ans].val;
154 }
155 
156 int find_nex(int x)
157 {
158     int ans = 2, q = root;
159     while (q)
160     {
161         if (x == tr[q].val)
162         {
163             if (tr[q].r > 0)
164             {
165                 q = tr[q].r;
166                 while (tr[q].l > 0) q = tr[q].l;
167                 ans = q;
168             }
169             break;
170         }
171         if (tr[q].val>x && tr[q].val<tr[ans].val) ans = q;
172         if (x < tr[q].val) q = tr[q].l;
173         else q = tr[q].r;
174     }
175     return tr[ans].val;
176 }
177 
178 int main()
179 {
180     build();
181 
182     int q;
183     scanf("%d", &q);
184     while (q--)
185     {
186         int op, x;
187         scanf("%d%d", &op, &x);
188         switch (op) 
189         {
190         case 1:
191         {
192             insert(root, x);
193             break;
194         }
195         case 2:
196         {
197             Delete(root, x);
198             break;
199         }
200         case 3:
201         {
202             printf("%d\n", find_rank(root, x) - 1);
203             break;
204         }
205         case 4:
206         {
207             printf("%d\n", find_num(root, x + 1));
208             break;
209         }
210         case 5:
211         {
212             printf("%d\n", find_befor(x));
213             break;
214         }
215 
216         case 6:
217         {
218             printf("%d\n", find_nex(x));
219             break;
220         }
221         }
222     }
223 }
View Code

 

【模板】文艺平衡树(题目):

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<vector>
  4 #include<iostream>
  5 #include<algorithm>
  6 using namespace std;
  7 
  8 const int N = 2000010;
  9 
 10 int n;
 11 int w[N];
 12 int lazy[N];
 13 int root;
 14 
 15 vector<int> ans;
 16 
 17 struct Node
 18 {
 19     int son[2], fa, val, size;
 20     Node() {}
 21 };
 22 
 23 Node tr[N];
 24 
 25 void update(int q)
 26 {
 27     tr[q].size = tr[tr[q].son[0]].size + tr[tr[q].son[1]].size + 1;
 28 }
 29 
 30 int build(int l, int r, int f)
 31 {
 32     int q = (l + r) >> 1;
 33     tr[q].fa = f;
 34     tr[q].val = w[q];
 35 
 36     if (l < q) tr[q].son[0] = build(l, q - 1, q);
 37     if (r > q) tr[q].son[1] = build(q + 1, r, q);
 38     update(q);
 39     return q;
 40 }
 41 
 42 void pushdown(int x)
 43 {
 44     if (!lazy[x]) return;
 45 
 46     lazy[tr[x].son[0]] ^= 1;
 47     lazy[tr[x].son[1]] ^= 1;
 48     swap(tr[x].son[0], tr[x].son[1]);
 49     lazy[x] = 0;
 50 }
 51 
 52 int find1(int x)
 53 {
 54     int q = root;
 55     while (true)
 56     {
 57         pushdown(q);
 58         if (tr[q].son[0] && tr[tr[q].son[0]].size >= x) q = tr[q].son[0];
 59         else
 60         {
 61             int rank = (tr[q].son[0] ? tr[tr[q].son[0]].size : 0) + 1;
 62             if (x <= rank) return q;
 63             x -= rank;
 64             q = tr[q].son[1];
 65         }
 66     }
 67 }
 68 
 69 void rotate(int x)
 70 {
 71     int y = tr[x].fa, z = tr[y].fa, k = tr[y].son[1] == x, w = tr[x].son[!k];
 72 
 73     if (z) tr[z].son[tr[z].son[1] == y] = x;
 74     else root = x;
 75     tr[y].son[k] = w;
 76     tr[x].son[!k] = y;
 77 
 78     if (w) tr[w].fa = y;
 79     tr[x].fa = z;
 80     tr[y].fa = x;
 81     update(y);
 82     update(x);
 83 }
 84 
 85 void splay(int x, int f)
 86 {
 87     while (tr[x].fa != f)
 88     {
 89         int y = tr[x].fa, z = tr[y].fa;
 90         if (z != f) rotate(((tr[y].son[1] == x) ^ (tr[z].son[1] == y)) ? x : y);
 91         rotate(x);
 92     }
 93 }
 94 
 95 void print(int x)
 96 {
 97     pushdown(x);
 98     if (tr[x].son[0]) print(tr[x].son[0]);
 99     ans.push_back(tr[x].val);
100     if (tr[x].son[1]) print(tr[x].son[1]);
101 }
102 
103 int main()
104 {
105     int q;
106     scanf("%d%d", &n,&q);
107 
108     for (int i = 1; i <= n + 2; i++) w[i] = i - 1;
109 
110     root = build(1, n + 2, 0);
111 
112     while (q--)
113     {
114         int l, r;
115         scanf("%d%d", &l, &r);
116         l = find1(l), r = find1(r + 2);
117         splay(l, 0), splay(r, l);
118         lazy[tr[tr[root].son[1]].son[0]] ^= 1;
119     }
120 
121     print(root);
122     for (int i = 0; i < n; i++) printf("%d ", ans[i + 1]);
123 }
View Code

 

【模板】二逼平衡树(题目):

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<iostream>
  4 #include<algorithm>
  5 using namespace std;
  6 
  7 const int N = 2000010, INF = 2147483647;
  8 
  9 int n;
 10 int a[N];
 11 
 12 struct Treap
 13 {
 14     struct Node
 15     {
 16         int l, r, val, size, dat, cnt;
 17         Node() {}
 18         Node(int l, int r, int val, int size, int cnt) :l(l), r(r), val(val), size(size), cnt(cnt) {}
 19     };
 20 
 21     int cnt;
 22     Node tr[N];
 23 
 24     int New(int x)
 25     {
 26         tr[++cnt] = Node(0, 0, x, 1, 1);
 27         tr[cnt].dat = rand();
 28         return cnt;
 29     }
 30 
 31     void update(int q)
 32     {
 33         tr[q].size = tr[tr[q].l].size + tr[q].cnt + tr[tr[q].r].size;
 34     }
 35 
 36     void zig(int& q) // 右旋
 37     {
 38         int p = tr[q].l;
 39         tr[q].l = tr[p].r;
 40         tr[p].r = q;
 41         q = p;
 42 
 43         update(tr[q].r);
 44         update(q);
 45     }
 46 
 47     void zag(int& q)
 48     {
 49         int p = tr[q].r;
 50         tr[q].r = tr[p].l;
 51         tr[p].l = q;
 52         q = p;
 53 
 54         update(tr[q].l);
 55         update(q);
 56     }
 57 
 58     void insert(int& q, int x)
 59     {
 60         if (!q)
 61         {
 62             q = New(x);
 63             update(q);
 64             return;
 65         }
 66 
 67         if (x == tr[q].val)
 68         {
 69             tr[q].cnt++;
 70             update(q);
 71             return;
 72         }
 73 
 74         if (x < tr[q].val)
 75         {
 76             insert(tr[q].l, x);
 77             if (tr[q].dat < tr[tr[q].l].dat) zig(q);
 78         }
 79         else
 80         {
 81             insert(tr[q].r, x);
 82             if (tr[q].dat < tr[tr[q].r].dat) zag(q);
 83         }
 84         update(q);
 85     }
 86 
 87     void Delete(int& q, int x)
 88     {
 89         if (!q) return;
 90         if (x == tr[q].val)
 91         {
 92             if (tr[q].cnt > 1)
 93             {
 94                 tr[q].cnt--;
 95                 update(q);
 96                 return;
 97             }
 98             if (tr[q].l || tr[q].r)
 99             {
100                 if (tr[q].r == 0 || tr[tr[q].l].dat > tr[tr[q].r].dat) zig(q), Delete(tr[q].r, x);
101                 else zag(q), Delete(tr[q].l, x);
102                 update(q);
103             }
104             else q = 0;
105             return;
106         }
107         else if (x < tr[q].val) Delete(tr[q].l, x);
108         else Delete(tr[q].r, x);
109         
110         if(q) update(q);
111     }
112 
113     int find_rank(int q, int x)
114     {
115         if (!q) return 0;
116         if (x == tr[q].val) return tr[tr[q].l].size;
117         else if (x < tr[q].val) return find_rank(tr[q].l, x);
118         else return find_rank(tr[q].r, x) + tr[q].cnt + tr[tr[q].l].size;
119     }
120 
121     int find_num(int q, int x)
122     {
123         if (!q) return INF;
124         if (x <= tr[tr[q].l].size) return find_num(tr[q].l, x);
125         else if (x <= tr[tr[q].l].size + 1) return tr[q].val;
126         return find_num(tr[q].r, x - tr[tr[q].l].size - tr[q].cnt);
127     }
128 
129     int find_pre(int p, int k)
130     {
131         if (!p) return -INF;
132         if (tr[p].val >= k) return find_pre(tr[p].l, k);
133         else return max(tr[p].val, find_pre(tr[p].r, k));
134     }
135 
136     int find_next(int p, int k)
137     {
138         if (!p) return INF;
139         if (tr[p].val <= k) return find_next(tr[p].r, k);
140         else return min(tr[p].val, find_next(tr[p].l, k));
141     }
142 };
143 
144 Treap treap;
145 
146 struct SEG
147 {
148     int root[N];
149 
150     void build(int q, int l, int r)
151     {
152         for (int i = l; i <= r; i++)
153         {
154             treap.insert(root[q], a[i]);
155         }
156 
157         if (l == r) return;
158         int mid = (l + r) >> 1;
159         build(q << 1, l, mid);
160         build(q << 1 | 1, mid + 1, r);
161     }
162 
163     int find_rank(int q, int l, int r, int L, int R, int x)
164     {
165         if (L > r || R < l) return 0;
166         if (L <= l && r <= R) return treap.find_rank(root[q], x);
167 
168         int mid = (l + r) >> 1;
169         return  find_rank(q << 1, l, mid, L, R, x) + find_rank(q << 1 | 1, mid + 1, r, L, R, x);
170     }
171 
172     int find_num(int L, int R, int k)
173     {
174         int l = 0, r = 1e8;
175         while (l < r)
176         {
177             int mid = (l + r + 1) >> 1;
178             if (find_rank(1, 1, n, L, R, mid) < k) l = mid;
179             else r = mid - 1;
180         }
181         return r;
182     }
183 
184     void modify(int q, int l, int r, int x, int k)
185     {
186         treap.Delete(root[q], a[x]);
187         treap.insert(root[q], k);
188 
189         if (l == r) return;
190 
191         int mid = (l + r) >> 1;
192         if (x <= mid) modify(q << 1, l, mid, x, k);
193         else modify(q << 1 | 1, mid + 1, r, x, k);
194     }
195 
196     int find_pre(int q, int l, int r, int L, int R, int x)
197     {
198         if (L > r || l > R) return -INF;
199         int mid = (l + r) >> 1;
200         if (L <= l && r <= R) return treap.find_pre(root[q], x);
201         else return max(find_pre(q << 1, l, mid, L, R, x), find_pre(q << 1 | 1, mid + 1, r, L, R, x));
202     }
203 
204     int find_next(int q, int l, int r, int L, int R, int x)
205     {
206         if (L > r || l > R) return INF;
207         int mid = (l + r) >> 1;
208         if (L <= l && r <= R) return treap.find_next(root[q], x);
209         else return min(find_next(q << 1, l, mid, L, R, x), find_next(q << 1 | 1, mid + 1, r, L, R, x));
210     }
211 };
212 
213 SEG seg;
214 
215 int main()
216 {
217     int m;
218     scanf("%d%d", &n, &m);
219     for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
220 
221     seg.build(1, 1, n);
222 
223     while (m--)
224     {
225         int op;
226         scanf("%d", &op);
227         if (op == 1)
228         {
229             int l, r, k;
230             scanf("%d%d%d", &l, &r, &k);
231             printf("%d\n", seg.find_rank(1, 1, n, l, r, k) + 1);
232         }
233         if (op == 2)
234         {
235             int l, r, k;
236             scanf("%d%d%d", &l, &r, &k);
237             printf("%d\n", seg.find_num(l, r, k));
238         }
239         if (op == 3)
240         {
241             int pos, k;
242             scanf("%d%d", &pos, &k);
243             seg.modify(1, 1, n, pos, k);
244             a[pos] = k;
245         }
246         if (op == 4)
247         {
248             int l, r, k;
249             scanf("%d%d%d", &l, &r, &k);
250             printf("%d\n", seg.find_pre(1, 1, n, l, r, k));
251         }
252         if (op == 5)
253         {
254             int l, r, k;
255             scanf("%d%d%d", &l, &r, &k);
256             printf("%d\n", seg.find_next(1, 1, n, l, r, k));
257         }
258     }
259 }
View Code

这题目就离谱

 

【BZOJ1251】序列终结者(题目):

  类似于线段树一样传翻转标记与相加标记

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<iostream>
  4 #include<algorithm>
  5 using namespace std;
  6 
  7 const int N = 200010;
  8 
  9 int n, m;
 10 int root, cnt;
 11 int num[N];
 12 int fa[N], son[N][2];
 13 int size1[N], v[N], mx[N];
 14 int add[N], rev[N];
 15 
 16 void pushup(int q)
 17 {
 18     size1[q] = size1[son[q][0]] + size1[son[q][1]] + 1;
 19     mx[q] = max(v[q], max(mx[son[q][0]], mx[son[q][1]]));
 20 }
 21 
 22 void pushdown(int q)
 23 {
 24     if (rev[q])
 25     {
 26         swap(son[q][0], son[q][1]);
 27         rev[son[q][0]] ^= 1;
 28         rev[son[q][1]] ^= 1;
 29         rev[q] = 0;
 30     }
 31 
 32     if (add[q])
 33     {
 34         if (son[q][0]) add[son[q][0]] += add[q], v[son[q][0]] += add[q], mx[son[q][0]] += add[q];
 35         if (son[q][1]) add[son[q][1]] += add[q], v[son[q][1]] += add[q], mx[son[q][1]] += add[q];
 36         add[q] = 0;
 37     }
 38 }
 39 
 40 int build(int l, int r, int pa)
 41 {
 42     if (l > r) return 0;
 43     int q = ++cnt;
 44     int mid = (l + r) >> 1;
 45 
 46     fa[q] = pa;
 47     v[q] = mx[q] = num[mid];
 48     son[q][0] = build(l, mid - 1, q);
 49     son[q][1] = build(mid + 1, r, q);
 50     pushup(q);
 51     return q;
 52 }
 53 
 54 int find(int x)
 55 {
 56     int q = root;
 57     while (q)
 58     {
 59         pushdown(q);
 60         if (x <= size1[son[q][0]]) q = son[q][0];
 61         else
 62         {
 63             x -= size1[son[q][0]] + 1;
 64             if (!x) return q;
 65             q = son[q][1];
 66         }
 67     }
 68     return 0;
 69 }
 70 
 71 void rotate(int x)
 72 {
 73     int y = fa[x], z = fa[y], k = son[y][1] == x, w = son[x][!k];
 74 
 75     pushdown(x);
 76     pushdown(y);
 77 
 78     if (z) son[z][son[z][1] == y] = x;
 79     son[y][k] = w;
 80     son[x][!k] = y;
 81 
 82     if (w) fa[w] = y;
 83     fa[y] = x;
 84     fa[x] = z;
 85 
 86     pushup(x);
 87     pushup(y);
 88 }
 89 
 90 void splay(int x, int pa)
 91 {
 92     while (fa[x] != pa)
 93     {
 94         int y = fa[x], z = fa[y];
 95         if (z != pa) rotate((son[y][1] == x) ^ (son[z][1] == y) ? x : y);
 96         rotate(x);
 97     }
 98     if (!pa) root = x;
 99 }
100 
101 void split(int l, int r)
102 {
103     l = find(l), r = find(r + 2);
104     splay(l, 0), splay(r, l);
105 }
106 
107 int main() 
108 {
109     scanf("%d%d", &n, &m);
110 
111     mx[0] = num[1] = num[n + 2] = -2e9;
112     root = build(1, n + 2, 0);
113 
114     while (m--)
115     {
116         int k, l, r, s;
117         scanf("%d%d%d", &k, &l, &r);
118         split(l, r);
119         if (k == 1)
120         {
121             scanf("%d", &s);
122             add[son[son[root][1]][0]] += s;
123             v[son[son[root][1]][0]] += s;
124             mx[son[son[root][1]][0]] += s;
125         }
126         else if (k == 2) rev[son[son[root][1]][0]] ^= 1;
127         else if (k == 3) printf("%d\n", mx[son[son[root][1]][0]]);
128     }
129 }
View Code

 

【BZOJ3262】陌上花开(题目):

  三维偏序模板,树状数组套平衡树,以b为关键字建树状数组,每个树状数组节点以c为关键字建平衡树,以a为关键字从小到大枚举进行插入操作(a一样大的要同时插入),在树状数组中插入b,每次插入再在当前节点的平衡树中插入c。

  完成当前a的插入操作后立即进行询问,这样能保证已经插入的所有元素的a都小于等于当期元素,询问时查询树状数组中小于b的节点所代表的平衡树中小于c的节点一共有多少,得出的便是答案。

  这不是CDQ模板么

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<iostream>
  4 #include<algorithm>
  5 using namespace std;
  6 
  7 const int N = 2000010;
  8 
  9 int n, k;
 10 
 11 struct SPLAY
 12 {
 13     struct tree
 14     {
 15         int val, fa, cnt, size, son[2];
 16         tree() {}
 17         tree(int val, int fa, int cnt, int size) :val(val), fa(fa), cnt(cnt), size(size) {}
 18     };
 19 
 20     int cnt = 0;
 21     tree tr[N];
 22 
 23     int New(int c)
 24     {
 25         cnt++;
 26         tr[cnt] = tree(c, 0, 1, 1);
 27         tr[cnt].son[0] = tr[cnt].son[1] = 0;
 28         return cnt;
 29     }
 30 
 31     void pushup(int q)
 32     {
 33         tr[q].size = tr[q].cnt;
 34         int ls = tr[q].son[0], rs = tr[q].son[1];
 35         if (ls) tr[q].size += tr[ls].size;
 36         if (rs) tr[q].size += tr[rs].size;
 37     }
 38 
 39     void rotate(int x)
 40     {
 41         int y = tr[x].fa, z = tr[y].fa, d = tr[y].son[1] == x, w = tr[x].son[!d];
 42 
 43         if (z) tr[z].son[tr[z].son[1] == y] = x;
 44         tr[y].son[d] = w;
 45         tr[x].son[!d] = y;
 46 
 47         if (w) tr[w].fa = y;
 48         tr[y].fa = x;
 49         tr[x].fa = z;
 50 
 51         pushup(y);
 52         pushup(x);
 53     }
 54 
 55     void splay(int x, int &rt)
 56     {
 57         if (x == rt) return;
 58         int pa = tr[rt].fa;
 59         while (tr[x].fa != pa)
 60         {
 61             int y = tr[x].fa, z = tr[y].fa;
 62             if (tr[y].fa != pa) rotate((tr[y].son[1] == x) ^ (tr[z].son[1] == y) ? x : y);
 63             rotate(x);
 64         }
 65         rt = x;
 66     }
 67 
 68     void insert(int& rt, int c)
 69     {
 70         if (!rt)
 71         {
 72             rt = New(c);
 73             return;
 74         }
 75 
 76         int q = rt;
 77         while (true)
 78         {
 79             tr[q].size++;
 80             if (tr[q].val == c)
 81             {
 82                 tr[q].cnt++;
 83                 return;
 84             }
 85             int d = c > tr[q].val;
 86             if (tr[q].son[d]) q = tr[q].son[d];
 87             else
 88             {
 89                 tr[q].son[d] = New(c);
 90                 tr[tr[q].son[d]].fa = q;
 91                 splay(tr[q].son[d], rt);
 92                 return;
 93             }
 94         }
 95     }
 96 
 97     int query(int q, int c)
 98     {
 99         if (!q) return 0;
100         if (tr[q].val == c) return (tr[q].son[0] ? tr[tr[q].son[0]].size : 0) + tr[q].cnt;
101         else if (tr[q].val > c) return query(tr[q].son[0], c);
102         else return (tr[q].son[0] ? tr[tr[q].son[0]].size : 0) + tr[q].cnt + query(tr[q].son[1], c);
103     }
104 };
105 SPLAY Splay;
106 
107 struct TREE
108 {
109     int root[N];
110 
111     int lowbit(int x)
112     {
113         return x & -x;
114     }
115 
116     void insert(int x, int y)
117     {
118         for (; x <= k; x += lowbit(x))
119         {
120             Splay.insert(root[x], y);
121         }
122     }
123 
124     int query(int x, int y)
125     {
126         int res = 0;
127         for (; x; x -= lowbit(x))
128         {
129             res += Splay.query(root[x], y);
130         }
131         return res;
132     }
133 };
134 TREE Tree;
135 
136 struct Node
137 {
138     int a, b, c;
139     Node() {}
140 };
141 
142 Node fl[N];
143 
144 bool cmp(Node a, Node b)
145 {
146     return a.a < b.a;
147 }
148 
149 int f[N], g[N];
150 bool st[N];
151 
152 int main()
153 {
154     scanf("%d%d", &n, &k);
155     for (int i = 1; i <= n; i++)
156     {
157         scanf("%d%d%d", &fl[i].a, &fl[i].b, &fl[i].c);
158     }
159 
160     sort(fl + 1, fl + 1 + n, cmp);
161 
162     for (int i = 1; i <= n; i++)
163     {
164         if (!st[i])
165         {
166             for (int j = i; fl[j].a == fl[i].a && j <= n; j++)
167             {
168                 Tree.insert(fl[j].b, fl[j].c);
169                 st[j] = true;
170             }
171         }
172         f[i] = Tree.query(fl[i].b, fl[i].c);
173     }
174 
175     for (int i = 1; i <= n; i++) g[f[i]]++;
176     for (int i = 1; i <= n; i++) printf("%d\n", g[i]);
177 }
View Code

 

【HNOI2012】永无乡(题目):

  并查集维护联通,Splay启发式合并(暴力合并)。

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<iostream>
  4 #include<algorithm>
  5 using namespace std;
  6 
  7 #define MAX 500000
  8 
  9 struct Node
 10 {
 11     int ch[2];
 12     int val, ff, size;
 13 }t[MAX];
 14 
 15 int f[MAX];
 16 int root[MAX], tot;
 17 int hh[MAX];
 18 int N, M;
 19 
 20 int getf(int x)
 21 {
 22     return x == f[x] ? x : f[x] = getf(f[x]);
 23 }
 24 
 25 inline void pushup(int x)
 26 {
 27     t[x].size = t[t[x].ch[0]].size + t[t[x].ch[1]].size + 1;
 28 }
 29 
 30 inline void rotate(int x)
 31 {
 32     int y = t[x].ff;
 33     int z = t[y].ff;
 34     int k = t[y].ch[1] == x;
 35     t[z].ch[t[z].ch[1] == y] = x; t[x].ff = z;
 36     t[y].ch[k] = t[x].ch[k ^ 1]; t[t[x].ch[k ^ 1]].ff = y;
 37     t[x].ch[k ^ 1] = y; t[y].ff = x;
 38     pushup(y); pushup(x);
 39 }
 40 
 41 inline void splay(int x, int goal)
 42 {
 43     while (t[x].ff != goal)
 44     {
 45         int y = t[x].ff, z = t[y].ff;
 46         if (z != goal)
 47             (t[z].ch[0] == y) ^ (t[y].ch[0] == x) ? rotate(x) : rotate(y);
 48         rotate(x);
 49     }
 50     if (goal <= N)root[goal] = x;
 51 }
 52 
 53 inline void insert(int x, int bh)
 54 {
 55     int u = root[bh], ff = bh;
 56     while (u && t[u].val != x)
 57         ff = u, u = t[u].ch[x > t[u].val];
 58     u = ++tot;
 59     t[u].size = 1;
 60     t[u].ff = ff;
 61     if (ff > N)
 62         t[ff].ch[x > t[ff].val] = u;
 63     t[u].val = x; t[u].ch[0] = t[u].ch[1] = 0;
 64     splay(u, bh);
 65 }
 66 
 67 void DFS(int u, int kk)
 68 {
 69     if (t[u].ch[0])DFS(t[u].ch[0], kk);
 70     if (t[u].ch[1])DFS(t[u].ch[1], kk);
 71     insert(t[u].val, kk);
 72 }
 73 
 74 inline void Merge(int a, int b)
 75 {
 76     int x = getf(a), y = getf(b);
 77     if (x == y)return;
 78     if (t[root[x]].size > t[root[y]].size)swap(x, y);
 79     f[x] = y;
 80     DFS(root[x], y);
 81 }
 82 
 83 int kth(int bh, int k)
 84 {
 85     int u = root[bh];
 86     if (t[u].size < k)return -1;
 87     while (233)
 88     {
 89         if (t[t[u].ch[0]].size + 1 < k)
 90         {
 91             k -= t[t[u].ch[0]].size + 1;
 92             u = t[u].ch[1];
 93         }
 94         else
 95             if (t[t[u].ch[0]].size >= k)
 96                 u = t[u].ch[0];
 97             else
 98                 return t[u].val;
 99     }
100 }
101 
102 int main()
103 {
104     scanf("%d%d", &N, &M);
105     for (int i = 1; i <= N; ++i)root[i] = i + N, f[i] = i;
106     tot = N + N;
107     for (int i = 1; i <= N; ++i)
108     {
109         int x;
110         scanf("%d", &x);
111         hh[x] = i;
112         t[i + N].val = x; t[i + N].size = 1; t[i + N].ff = i;
113     }
114     for (int i = 1; i <= M; ++i)
115     {
116         int x, y;
117         scanf("%d%d", &x, &y);
118         Merge(x, y);
119     }
120     int Q;
121     scanf("%d", &Q);
122     while (Q--)
123     {
124         char ch[3]; int a, b;
125         scanf("%s%d%d", ch, &a, &b);
126         if (ch[0] == 'B')
127         {
128             Merge(a, b);
129         }
130         else
131         {
132             int ans = kth(getf(a), b);
133             printf("%d\n", ans == -1 ? ans : hh[ans]);
134         }
135     }
136     return 0;
137 }
View Code

 

【CF414E】Mashmokh's Designed Problem(题目

不会

【BZOJ3600】没有人的算术(题目

  用一个实数来代表pair值,SGT来插入,线段树查询,具体看代码

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<iostream>
  4 #include<algorithm>
  5 using namespace std;
  6 
  7 typedef long long LL;
  8 
  9 LL read()
 10 {
 11     LL x = 0, f = 0;
 12     char ch = getchar();
 13     while (!isdigit(ch)) f = ch == '-', ch = getchar();
 14     while (isdigit(ch)) x = x * 10 + ch - '0', ch = getchar();
 15     return f ? -x : x;
 16 }
 17 
 18 const int N = 500010;
 19 
 20 int n, m;
 21 int root, R, top;
 22 int mx[N], pos[N], id[N];
 23 double a[N];
 24 char ch[5];
 25 
 26 struct Node 
 27 {
 28     int l, r;
 29     Node() {}
 30     Node(int l, int r) :l(l), r(r) {}
 31 
 32     friend bool operator > (Node x, Node y)
 33     {
 34         if (a[x.l] > a[y.l])return 1;
 35         if (a[x.l] == a[y.l] && a[x.r] > a[y.r])return 1;
 36         return 0;
 37     }
 38 
 39     friend bool operator == (Node x, Node y)
 40     {
 41         if (x.l != y.l || x.r != y.r)return 0;
 42         return 1;
 43     }
 44 };
 45 
 46 struct SGTree
 47 {
 48     int cnt;
 49     Node v[N];
 50     int siz[N], ls[N], rs[N];
 51 
 52     void dfs(int k)
 53     {
 54         if (!k)return;
 55         dfs(ls[k]);
 56         id[++top] = k;
 57         dfs(rs[k]);
 58     }
 59 
 60     void pushup(int q)
 61     {
 62         siz[q] = siz[ls[q]] + siz[rs[q]] + 1;
 63     }
 64 
 65     void build(int& q, int l, int r, double L, double R) // 建树
 66     {
 67         if (l > r) 
 68         {
 69             q = 0; 
 70             return; 
 71         }
 72 
 73         double vmid = (L + R) / 2.0;
 74         int mid = (l + r) / 2;
 75 
 76         q = id[mid];
 77         a[q] = vmid;
 78         build(ls[q], l, mid - 1, L, vmid);
 79         build(rs[q], mid + 1, r, vmid, R);
 80         pushup(q);
 81     }
 82 
 83     void rebuild(int& q, double l, double r) // 重构
 84     {
 85         top = 0;
 86         dfs(q);
 87         build(q, 1, top, l, r);
 88     }
 89 
 90     int insert(int& q, double l, double r, Node val) 
 91     {
 92         double mv = (l + r) / 2.0;
 93         if (!q)
 94         {
 95             q = ++cnt; 
 96             a[q] = mv;
 97             v[q] = val; 
 98             siz[q] = 1;
 99             return q;
100         }
101 
102         int p;
103         if (val == v[q]) return q;
104         else
105         {
106             siz[q]++;
107             if (val > v[q]) p = insert(rs[q], mv, r, val);
108             else p = insert(ls[q], l, mv, val);
109         }
110         if (siz[q] * 0.75 > max(siz[ls[q]], siz[rs[q]]))
111         {
112             if (R)
113             {
114                 if (ls[q] == R) rebuild(ls[q], l, mv);
115                 else rebuild(rs[q], mv, r);
116                 R = 0;
117             }
118         }
119         else R = q;
120         return p;
121     }
122 }SGT;
123 
124 void modify(int k, int l, int r, int v)
125 {
126     if (l == r)
127     {
128         mx[k] = l;
129         return; 
130     }
131 
132     int mid = (l + r) >> 1;
133     if (v <= mid) modify(k << 1, l, mid, v);
134     else modify(k << 1 | 1, mid + 1, r, v);
135 
136     int x = mx[k << 1], y = mx[k << 1 | 1];
137     if (a[pos[x]] >= a[pos[y]]) mx[k] = x;
138     else mx[k] = y;
139 }
140 
141 int query(int k, int l, int r, int x, int y)
142 {
143     if (l == x && y == r) return mx[k];
144     int t = 0, p = 0;
145     int mid = (l + r) >> 1;
146     if (x <= mid)
147     {
148         p = query(k << 1, l, mid, x, min(mid, y));
149         if (a[pos[p]] > a[pos[t]])t = p;
150     }
151     if (y > mid)
152     {
153         p = query(k << 1 | 1, mid + 1, r, max(x, mid + 1), y);
154         if (a[pos[p]] > a[pos[t]])t = p;
155     }
156     return t;
157 }
158 
159 int main()
160 {
161     n = read(), m = read();
162     a[0] = -1;
163     SGT.insert(root, 0, 1, Node(0, 0));
164 
165     for (int i = 1; i <= n; i++) pos[i] = 1;
166     for (int i = 1; i <= n; i++) modify(1, 1, n, i);
167 
168     for (int i = 1; i <= m; i++)
169     {
170         scanf("%s", ch + 1);
171         int l = read(), r = read();
172         if (ch[1] == 'C')
173         {
174             int K = read();
175             pos[K] = SGT.insert(root, 0, 1, Node(pos[l], pos[r]));
176             if (R) SGT.rebuild(root, 0, 1); R = 0;
177             modify(1, 1, n, K);
178         }
179         else printf("%d\n", query(1, 1, n, l, r));
180     }
181 }
View Code

 

LCT:

  概念看

【BZOJ2049】

模板

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<iostream>
  4 #include<algorithm>
  5 using namespace std;
  6 
  7 const int N = 10010;
  8 const int inf = 1e9;
  9 
 10 inline int read()
 11 {
 12     int x = 0, f = 1; char ch = getchar();
 13     while (ch < '0' || ch>'9') { if (ch == '-') f = -1; ch = getchar(); }
 14     while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
 15     return x * f;
 16 }
 17 
 18 int n, m;
 19 int fa[N], c[N][2], st[N];
 20 bool rev[N];
 21 
 22 inline bool isroot(int x)
 23 {
 24     return c[fa[x]][0] != x && c[fa[x]][1] != x;
 25 }
 26 
 27 void pushdown(int k)
 28 {
 29     int l = c[k][0], r = c[k][1];
 30     if (rev[k])
 31     {
 32         rev[k] ^= 1; rev[l] ^= 1; rev[r] ^= 1;
 33         swap(c[k][0], c[k][1]);
 34     }
 35 }
 36 
 37 void rotate(int x)
 38 {
 39     int y = fa[x], z = fa[y], l, r;
 40     if (c[y][0] == x)l = 0; else l = 1; r = l ^ 1;
 41     if (!isroot(y))
 42     {
 43         if (c[z][0] == y)c[z][0] = x; else c[z][1] = x;
 44     }
 45     fa[x] = z; fa[y] = x; fa[c[x][r]] = y;
 46     c[y][l] = c[x][r]; c[x][r] = y;
 47 }
 48 
 49 void splay(int x)
 50 {
 51     int top = 0; st[++top] = x;
 52     for (int i = x; !isroot(i); i = fa[i])
 53     {
 54         st[++top] = fa[i];
 55     }
 56     for (int i = top; i; i--)pushdown(st[i]);
 57     while (!isroot(x))
 58     {
 59         int y = fa[x], z = fa[y];
 60         if (!isroot(y))
 61         {
 62             if (c[y][0] == x ^ c[z][0] == y)rotate(x);
 63             else rotate(y);
 64         }
 65         rotate(x);
 66     }
 67 }
 68 
 69 void access(int x)
 70 {
 71     int t = 0;
 72     while (x)
 73     {
 74         splay(x);
 75         c[x][1] = t;
 76         t = x; x = fa[x];
 77     }
 78 }
 79 
 80 void rever(int x)
 81 {
 82     access(x); splay(x); rev[x] ^= 1;
 83 }
 84 
 85 void link(int x, int y)
 86 {
 87     rever(x); fa[x] = y; splay(x);
 88 }
 89 
 90 void cut(int x, int y)
 91 {
 92     rever(x); access(y); splay(y); c[y][0] = fa[x] = 0;
 93 }
 94 
 95 int find(int x)
 96 {
 97     access(x); splay(x);
 98     int y = x;
 99     while (c[y][0])y = c[y][0];
100     return y;
101 }
102 
103 int main()
104 {
105     char ch[10];
106     int x, y;
107     n = read(); m = read();
108     for (int i = 1; i <= m; i++)
109     {
110         scanf("%s", ch);
111         x = read(); y = read();
112         if (ch[0] == 'C')link(x, y);
113         else if (ch[0] == 'D')cut(x, y);
114         else
115         {
116             if (find(x) == find(y))printf("Yes\n");
117             else printf("No\n");
118         }
119     }
120     return 0;
121 }
View Code

 

【BZOJ2631】

模板

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<iostream>
  4 #include<algorithm>
  5 using namespace std;
  6 
  7 typedef unsigned int UIT;
  8 
  9 int read()
 10 {
 11     int x = 0, f = 1; char ch = getchar();
 12     while (ch < '0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
 13     while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
 14     return x * f;
 15 }
 16 
 17 const int N = 100010;
 18 const int mod = 51061;
 19 
 20 int n, m, top, cnt;
 21 int c[N][2], fa[N];
 22 int siz[N], q[N];
 23 bool rev[N];
 24 UIT sum[N], val[N], at[N], mt[N];
 25 
 26 void cal(int x, int m, int a)
 27 {
 28     if (!x)return;
 29     val[x] = (val[x] * m + a) % mod;
 30     sum[x] = (sum[x] * m + a * siz[x]) % mod;
 31     at[x] = (at[x] * m + a) % mod;
 32     mt[x] = (mt[x] * m) % mod;
 33 }
 34 
 35 bool isroot(int x)
 36 {
 37     return c[fa[x]][0] != x && c[fa[x]][1] != x;
 38 }
 39 
 40 void update(int x)
 41 {
 42     int l = c[x][0], r = c[x][1];
 43     sum[x] = (sum[l] + sum[r] + val[x]) % mod;
 44     siz[x] = (siz[l] + siz[r] + 1) % mod;
 45 }
 46 
 47 void pushdown(int x)
 48 {
 49     int l = c[x][0], r = c[x][1];
 50     if (rev[x])
 51     {
 52         rev[x] ^= 1; rev[l] ^= 1; rev[r] ^= 1;
 53         swap(c[x][0], c[x][1]);
 54     }
 55     int m = mt[x], a = at[x];
 56     mt[x] = 1; 
 57     at[x] = 0;
 58     if (m != 1 || a != 0)
 59     {
 60         cal(l, m, a); cal(r, m, a);
 61     }
 62 }
 63 
 64 void rotate(int x)
 65 {
 66     int y = fa[x], z = fa[y], l, r;
 67     l = (c[y][1] == x); 
 68     r = l ^ 1;
 69 
 70     if (!isroot(y)) c[z][c[z][1] == y] = x;
 71     fa[x] = z;
 72     fa[y] = x; 
 73     fa[c[x][r]] = y;
 74     c[y][l] = c[x][r];
 75     c[x][r] = y;
 76 
 77     update(y);
 78     update(x);
 79 }
 80 
 81 void splay(int x)
 82 {
 83     q[++top] = x;
 84     for (int i = x; !isroot(i); i = fa[i]) q[++top] = fa[i];
 85 
 86     while (top) pushdown(q[top--]);
 87     while (!isroot(x))
 88     {
 89         int y = fa[x], z = fa[y];
 90         if (!isroot(y))
 91         {
 92             if (c[y][0] == x ^ c[z][0] == y) rotate(x);
 93             else rotate(y);
 94         }
 95         rotate(x);
 96     }
 97 }
 98 
 99 void access(int x)
100 {
101     for (int t = 0; x; t = x, x = fa[x])
102     {
103         splay(x);
104         c[x][1] = t; 
105         update(x);
106     }
107 }
108 
109 void makeroot(int x)
110 {
111     access(x);
112     splay(x);
113     rev[x] ^= 1;
114 }
115 
116 void split(int x, int y)
117 {
118     makeroot(y); 
119     access(x);
120     splay(x);
121 }
122 
123 void link(int x, int y)
124 {
125     makeroot(x);
126     fa[x] = y;
127 }
128 
129 void cut(int x, int y)
130 {
131     makeroot(x);
132     access(y);
133     splay(y);
134     c[y][0] = fa[x] = 0;
135 }
136 
137 int main()
138 {
139     n = read();
140     m = read();
141 
142     for (int i = 1; i <= n; i++) val[i] = sum[i] = mt[i] = siz[i] = 1;
143 
144     for (int i = 1; i < n; i++)
145     {
146         int u = read(), v = read();
147         link(u, v);
148     }
149 
150     char ch[5];
151     while (m--)
152     {
153         scanf("%s", ch);
154         int u = read(), v = read();
155         if (ch[0] == '+')
156         {
157             int x = read();
158             split(u, v); cal(u, 1, x);
159         }
160         if (ch[0] == '-')
161         {
162             cut(u, v);
163             u = read(); v = read(); link(u, v);
164         }
165         if (ch[0] == '*')
166         {
167             int x = read();
168             split(u, v); cal(u, x, 0);
169         }
170         if (ch[0] == '/')
171         {
172             split(u, v);
173             printf("%d\n", sum[u]);
174         }
175     }
176 }
View Code

 

【BZOJ4389】

模板

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<iostream>
  4 #include<algorithm>
  5 using namespace std;
  6 
  7 const int N = 200010;
  8 
  9 typedef long long LL;
 10 
 11 int n, m;
 12 
 13 int f[N], son[N][2], tmp[N], c[N]; 
 14 bool rev[N];
 15 LL v[N], s[N], mx[N], tc[N], ta[N];
 16 LL st[N], sa[N], as[N];
 17 
 18 inline void read(int& a)
 19 { 
 20     char c;
 21     while (!(((c = getchar()) >= '0') && (c <= '9')));
 22     a = c - '0';
 23     while (((c = getchar()) >= '0') && (c <= '9'))(a *= 10) += c - '0'; 
 24 }
 25 
 26 inline bool isroot(int x)
 27 { 
 28     return !f[x] || son[f[x]][0] != x && son[f[x]][1] != x;
 29 }
 30 
 31 inline void rev1(int x) 
 32 { 
 33     if (!x)return; 
 34     swap(son[x][0], son[x][1]);
 35     rev[x] ^= 1; 
 36 }
 37 
 38 inline void col1(int x, LL y)
 39 {
 40     if (!x)return;
 41     v[x] = mx[x] = tc[x] = y;
 42     s[x] = y * c[x];
 43     ta[x] = 0;
 44     sa[x] = s[x] + st[x];
 45 }
 46 
 47 inline void add1(int x, LL y) 
 48 {
 49     if (!x)return;
 50     v[x] += y;
 51     s[x] += y * c[x];
 52     mx[x] += y;
 53     if (tc[x])tc[x] += y; else ta[x] += y;
 54     sa[x] = s[x] + st[x];
 55 }
 56 
 57 inline void pb(int x) 
 58 {
 59     if (rev[x]) rev1(son[x][0]), rev1(son[x][1]), rev[x] = 0;
 60     if (tc[x]) col1(son[x][0], tc[x]), col1(son[x][1], tc[x]), tc[x] = 0;
 61     if (ta[x]) add1(son[x][0], ta[x]), add1(son[x][1], ta[x]), ta[x] = 0;
 62 }
 63 
 64 inline void up(int x) 
 65 {
 66     s[x] = mx[x] = v[x]; c[x] = 1;
 67     st[x] = as[x];
 68     for (int i = 0; i < 2; i++)
 69     {
 70         int y = son[x][i];
 71         if (y) {
 72             c[x] += c[y];
 73             s[x] += s[y];
 74             mx[x] = max(mx[x], mx[y]);
 75             st[x] += st[y];
 76         }
 77     }
 78     sa[x] = s[x] + st[x];
 79 }
 80 
 81 inline void rotate(int x) 
 82 {
 83     int y = f[x], w = son[y][1] == x;
 84     son[y][w] = son[x][w ^ 1];
 85     if (son[x][w ^ 1]) f[son[x][w ^ 1]] = y;
 86     if (f[y])
 87     {
 88         int z = f[y];
 89         if (son[z][0] == y) son[z][0] = x; 
 90         else if (son[z][1] == y) son[z][1] = x;
 91     }
 92     f[x] = f[y];
 93     f[y] = x; 
 94     son[x][w ^ 1] = y;
 95     up(y);
 96 }
 97 
 98 inline void splay(int x) 
 99 {
100     int s = 1, i = x, y; 
101     tmp[1] = i;
102     while (!isroot(i)) tmp[++s] = i = f[i];
103     while (s) pb(tmp[s--]);
104     while (!isroot(x))
105     {
106         y = f[x];
107         if (!isroot(y)) { if ((son[f[y]][0] == y) ^ (son[y][0] == x))rotate(x); else rotate(y); }
108         rotate(x);
109     }
110     up(x);
111 }
112 
113 inline void access(int x)
114 {
115     for (int y = 0; x; y = x, x = f[x]) 
116     {
117         splay(x);
118         if (son[x][1]) as[x] += sa[son[x][1]];
119         if (son[x][1] = y) as[x] -= sa[y];
120         up(x);
121     }
122 }
123 
124 inline void makeroot(int x) 
125 { 
126     access(x);
127     splay(x);
128     rev1(x); 
129 }
130 
131 inline void link(int x, int y)
132 {
133     makeroot(x);
134     makeroot(y);
135     as[y] += sa[x];
136     f[x] = y;
137     access(x);
138 }
139 
140 inline void cutf(int x)
141 { 
142     access(x); 
143     splay(x); 
144     f[son[x][0]] = 0; 
145     son[x][0] = 0; 
146     up(x);
147 }
148 
149 inline void cut(int x, int y) 
150 { 
151     makeroot(x); 
152     cutf(y); 
153 }
154 
155 inline void col(int x, int y, int z)
156 {
157     makeroot(x);
158     access(y); 
159     splay(y); 
160     col1(y, z); 
161 }
162 
163 inline void add(int x, int y, int z) 
164 { 
165     makeroot(x); 
166     access(y); 
167     splay(y);
168     add1(y, z);
169 }
170 
171 inline LL chainsum(int x, int y) 
172 { 
173     makeroot(x);
174     access(y);
175     splay(y);
176     return s[y]; 
177 }
178 
179 inline LL chainmax(int x, int y) 
180 { 
181     makeroot(x); 
182     access(y); 
183     splay(y);
184     return mx[y]; 
185 }
186 
187 inline LL subtreesum(int x, int y) 
188 { 
189     makeroot(x); 
190     access(y); 
191     splay(y);
192     return as[y] + v[y]; 
193 }
194 
195 int main() 
196 {
197     read(n);
198     for (int i = 1; i <= n; i++)
199     {
200         int x;
201         read(x);
202         v[i] = s[i] = mx[i] = sa[i] = x, c[i] = 1;
203     }
204     for (int i = 2; i <= n; i++)
205     {
206         int x;
207         read(x);
208         link(x, i);
209     }
210     read(m);
211     while (m--) 
212     {
213         int op, x, y, z;
214         read(op), read(x), read(y);
215         if (op == 1) read(z), add(x, y, z);
216         if (op == 2) read(z), col(x, y, z);
217         if (op == 3) printf("%lld\n", subtreesum(x, y));
218         if (op == 4) printf("%lld\n", chainmax(x, y));
219         if (op == 5) printf("%lld\n", chainsum(x, y));
220         if (op == 6) link(x, y);
221         if (op == 7) cut(x, y);
222     }
223 }
View Code

 

posted on 2020-07-17 22:24  ArrogHie  阅读(369)  评论(0)    收藏  举报