【樹鏈剖分】大冰隙2
阿新 • • 發佈:2020-08-19
題意
給出一個01序列,序列中的01會抵消掉,相當於括號匹配。
給出一段區間,進行2種操作:1、求出區間去掉匹配的01後最大的值(另外給出)。2、修改值。
\(n\leq 100000\ m \leq 100000\)
思路
把01當成括號序列匹配一樣進棧,根據此建一棵樹。
那麼01的序列自然會抵消掉,剩下的查詢序列之間就只有3種情況:1111111..000000..11111100000之類
利用樹鏈剖分對樹上進行操作。
程式碼
#include <cstdio> #include <stdlib.h> #include <algorithm> using namespace std; int n, m, cnt, tot; int op[100001], a[100001], pos[100001]; int head[100001], ver[200001], next[200001]; int fa[100001], dep[100001], size[100001], son[100001], top[100001], seg[100001]; pair<int, int> v[100001], rev[100001]; void add(int u, int v) { ver[++tot] = v; next[tot] = head[u]; head[u] = tot; } void dfs1(int u) { size[u] = 1; dep[u] = dep[fa[u]] + 1; for (int i = head[u]; i; i = next[i]) { if (ver[i] == fa[u]) continue; dfs1(ver[i]); size[u] += size[ver[i]]; if (size[ver[i]] > size[son[u]]) son[u] = ver[i]; } } void dfs2(int u, int t) { top[u] = t; seg[u] = ++cnt; rev[cnt] = v[u]; if (!son[u]) return; dfs2(son[u], t); for (int i = head[u]; i; i = next[i]) { if (top[ver[i]]) continue; dfs2(ver[i], ver[i]); } } struct treenode { int maxv[400001]; void update(int p) { maxv[p] = max(maxv[p << 1], maxv[p << 1 | 1]); } void build(int type, int p, int l, int r) { if (l == r) { maxv[p] = type ? rev[l].second : rev[l].first; return; } int mid = l + r >> 1; build(type, p << 1, l, mid); build(type, p << 1 | 1, mid + 1, r); update(p); } void modify(int type, int p, int l, int r, int pp, int val) { if (l == r) { maxv[p] = val; type ? rev[l].second = val : rev[l].first = val; return; } int mid = l + r >> 1; if (pp <= mid) modify(type, p << 1, l, mid, pp, val); else modify(type, p << 1 | 1, mid + 1, r, pp, val); update(p); } int find(int p, int l, int r, int L, int R) { if (L <= l && r <= R) return maxv[p]; int res = 0; int mid = l + r >> 1; if (L <= mid) res = max(res, find(p << 1, l, mid, L, R)); if (R > mid) res = max(res, find(p << 1 | 1, mid + 1, r, L, R)); return res; } }t0, t1; int query(int type, int x, int y) { int res = 0; while (top[x] != top[y]) { if (dep[top[x]] < dep[top[y]]) swap(x, y), type ^= 1; res = type ? max(res, t1.find(1, 1, cnt, seg[top[x]], seg[x])) : max(res, t0.find(1, 1, cnt, seg[top[x]], seg[x])); x = fa[top[x]]; } if (x == y) return res; if(dep[x] > dep[y]) swap(x, y); else type ^= 1; res = type ? max(res, t1.find(1, 1, cnt, seg[son[x]], seg[y])) : max(res, t0.find(1, 1, cnt, seg[son[x]], seg[y])); return res; } int main() { int size = 256 << 20; char *p = (char*) malloc(size) + size; __asm__("movl %0, %%esp\n" :: "r"(p)); scanf("%d %d", &n, &m); for (int i = 1; i <= n; i++) scanf("%d", &op[i]); for (int i = 1; i <= n; i++) scanf("%d", &a[i]); int nn = 1, root = 1, now = 1; for (int i = 1; i <= n; i++) { if (!op[i]) { pos[i] = ++nn; add(nn, now), add(now, nn); v[nn].first = a[i]; fa[nn] = now; now = nn; } else { pos[i] = now; v[now].second = a[i]; if (root == now) { root = ++nn; add(now, root), add(root, now); fa[now] = root; now = root; } else now = fa[now]; } } dfs1(root); dfs2(root, root); t0.build(0, 1, 1, cnt); t1.build(1, 1, 1, cnt); for (int x, y, ml; m; m--) { scanf("%d %d %d", &ml, &x, &y); if (ml == 1) { a[x] = y; op[x] ? t1.modify(1, 1, 1, cnt, seg[pos[x]], y) : t0.modify(1, 1, 1, cnt, seg[pos[x]], y); } else { if (x == y) { printf("%d\n", a[x]); continue; } int px = pos[x], py = pos[y]; if(op[x] == 0) px = fa[px]; if(op[y] == 1) py = fa[py]; printf("%d\n", query(1, px, py)); } } }