题目大意:维护一棵树,每次删边加边、给一条路径的所有点赋一个值、给一条路径的所有点加上一个值,或询问一条路径上的第二大值及其在这条路径上的出现次数。
思路:算是LCT的模板题吧,维护每个区间的第一大值和第一大值的出现次数,第二大值和第二大值的出现次数。
PS:终于搞出了一个指针版,新模板出来啦~~~
犯过的错误:
1、LCT里splay的旋转和普通splay的旋转有所不同。
2、不能更新超级儿子 nil 的最值。
代码(2859MS):
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <iostream> 5 using namespace std; 6 typedef long long LL; 7 #define FOR(i, n) for(int i = 0; i < n; ++i) 8 9 const int MAXV = 100010; 10 const int MAXE = MAXV << 1; 11 const int INF = 0x3f3f3f3f; 12 const int NINF = -INF; 13 14 struct LCT { 15 struct Node { 16 Node *ch[2], *fa; 17 int val, set, add; 18 int max[2], cnt[2], size; 19 bool rt, rev; 20 } statePool[MAXV], *nil; 21 int ncnt; 22 23 int head[MAXV], val[MAXV], ecnt; 24 int to[MAXE], next[MAXE]; 25 int n, m, T; 26 Node *ptr[MAXV]; 27 28 LCT() { 29 ptr[0] = nil = statePool; 30 nil->size = 0; 31 FOR(k, 2) nil->max[k] = NINF; 32 } 33 34 void init() { 35 memset(head + 1, -1, n * sizeof(int)); 36 ncnt = 1; 37 ecnt = 0; 38 } 39 40 void add_edge(int u, int v) { 41 to[ecnt] = v; next[ecnt] = head[u]; head[u] = ecnt++; 42 to[ecnt] = u; next[ecnt] = head[v]; head[v] = ecnt++; 43 } 44 45 Node* new_node(int val, Node *f) { 46 Node* x = &statePool[ncnt++]; 47 x->ch[0] = x->ch[1] = nil; x->fa = f; 48 x->val = val; x->set = NINF; x->add = 0; 49 x->max[0] = val; x->cnt[0] = 1; 50 x->max[1] = NINF; 51 x->size = 1; 52 x->rt = true; x->rev = false; 53 return x; 54 } 55 56 void dfs(int u, int f) { 57 ptr[u] = new_node(val[u], ptr[f]); 58 for(int p = head[u]; ~p; p = next[p]) { 59 int v = to[p]; 60 if(v == f) continue; 61 dfs(v, u); 62 } 63 } 64 65 void get_max(int &a, int &b, int c) { 66 if(a != c) { 67 if(b < c) swap(b, c); 68 if(a < b) swap(a, b); 69 } 70 } 71 72 void cnt_max(int a, int &cnt, int b, int bcnt) { 73 if(a != NINF && a == b) cnt += bcnt; 74 } 75 76 void update(Node *x) { 77 x->size = x->ch[0]->size + x->ch[1]->size + 1; 78 79 x->max[0] = x->val; x->max[1] = NINF; 80 FOR(i, 2) FOR(j, 2) 81 get_max(x->max[0], x->max[1], x->ch[i]->max[j]); 82 83 FOR(k, 2) x->cnt[k] = 0; 84 FOR(k, 2) cnt_max(x->max[k], x->cnt[k], x->val, 1); 85 FOR(k, 2) FOR(i, 2) FOR(j, 2) 86 cnt_max(x->max[k], x->cnt[k], x->ch[i]->max[j], x->ch[i]->cnt[j]); 87 } 88 89 void rotate(Node *x) { 90 Node *y = x->fa; 91 int t = (y->ch[1] == x); 92 93 if(y->rt) y->rt = false, x->rt = true; 94 else y->fa->ch[y->fa->ch[1] == y] = x; 95 x->fa = y->fa; 96 97 (y->ch[t] = x->ch[t ^ 1])->fa = y; 98 (x->ch[t ^ 1] = y)->fa = x; 99 update(y); 100 } 101 102 void update_set(Node *x, int val) { 103 if(x == nil) return ; 104 x->add = 0; 105 x->val = x->set = val; 106 x->max[0] = val; x->cnt[0] = x->size; 107 x->max[1] = NINF; 108 } 109 110 void update_add(Node *x, int val) { 111 if(x == nil) return ; 112 x->add += val; 113 x->val += val; 114 FOR(k, 2) if(x->max[k] != NINF) 115 x->max[k] += val; 116 } 117 118 void update_rev(Node *x) { 119 if(x == nil) return ; 120 x->rev = !x->rev; 121 swap(x->ch[0], x->ch[1]); 122 } 123 124 void pushdown(Node *x) { 125 if(x->set != NINF) { 126 FOR(k, 2) update_set(x->ch[k], x->set); 127 x->set = NINF; 128 } 129 if(x->add != 0) { 130 FOR(k, 2) update_add(x->ch[k], x->add); 131 x->add = 0; 132 } 133 if(x->rev) { 134 FOR(k, 2) update_rev(x->ch[k]); 135 x->rev = false; 136 } 137 } 138 139 void push(Node *x) { 140 if(!x->rt) push(x->fa); 141 pushdown(x); 142 } 143 144 void splay(Node *x) { 145 push(x); 146 while(!x->rt) { 147 Node *f = x->fa, *ff = f->fa; 148 if(!f->rt) rotate(((ff->ch[1] == f) && (f->ch[1] == x)) ? f : x); 149 rotate(x); 150 } 151 update(x); 152 } 153 154 Node* access(Node *x) { 155 Node *y = nil; 156 while(x != nil) { 157 splay(x); 158 x->ch[1]->rt = true; 159 (x->ch[1] = y)->rt = false; 160 update(x); 161 y = x; x = x->fa; 162 } 163 return y; 164 } 165 166 void be_root(Node *x) { 167 access(x); 168 splay(x); 169 update_rev(x); 170 } 171 172 void link(Node *x, Node *y) { 173 be_root(x); 174 x->fa = y; 175 } 176 177 void cut(Node *x, Node *y) { 178 be_root(x); 179 access(x); 180 splay(y); 181 y->fa = nil; 182 } 183 184 void modify_add(Node *x, Node *y, int w) { 185 be_root(x); 186 update_add(access(y), w); 187 } 188 189 void modify_set(Node *x, Node *y, int w) { 190 be_root(x); 191 update_set(access(y), w); 192 } 193 194 void query(Node *x, Node *y) { 195 be_root(x); 196 Node *r = access(y); 197 if(r->max[1] == NINF) puts("ALL SAME"); 198 else printf("%d %d\n", r->max[1], r->cnt[1]); 199 } 200 201 void work() { 202 scanf("%d", &T); 203 for(int t = 1; t <= T; ++t) { 204 scanf("%d%d", &n, &m); 205 init(); 206 for(int i = 1; i <= n; ++i) scanf("%d", &val[i]); 207 for(int i = 1, u, v; i < n; ++i) { 208 scanf("%d%d", &u, &v); 209 add_edge(u, v); 210 } 211 dfs(1, 0); 212 printf("Case #%d:\n", t); 213 for(int i = 0, x, y, a, b, op; i < m; ++i) { 214 scanf("%d", &op); 215 if(op == 1) { 216 scanf("%d%d%d%d", &x, &y, &a, &b); 217 cut(ptr[x], ptr[y]); 218 link(ptr[a], ptr[b]); 219 } else if(op == 2) { 220 scanf("%d%d%d", &a, &b, &x); 221 modify_set(ptr[a], ptr[b], x); 222 } else if(op == 3) { 223 scanf("%d%d%d", &a, &b, &x); 224 modify_add(ptr[a], ptr[b], x); 225 } else { 226 scanf("%d%d", &a, &b); 227 query(ptr[a], ptr[b]); 228 } 229 } 230 } 231 } 232 } S; 233 234 int main() { 235 S.work(); 236 }