1. 程式人生 > 實用技巧 >【樹鏈剖分】大冰隙2

【樹鏈剖分】大冰隙2

題意

給出一個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));
		}
	}
}