제출 #1227066

#제출 시각아이디문제언어결과실행 시간메모리
1227066chaeryeongTourism (JOI23_tourism)C++20
100 / 100
4264 ms31220 KiB
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5 + 1;
const int B = 18;
vector <int> adj[N];
int n, m, q, ans[N], p[N], sze[N], in[N], nxt[N], tt, dep[N], a[N], dp[B][N];
vector <pair <int, int>> queries[N];
void dfs1 (int pos, int par) {
	p[pos] = par;
	dp[0][pos] = p[pos];
	for (int i = 1; i < B; i++) {
		dp[i][pos] = dp[i - 1][dp[i - 1][pos]];
	}
	if (par != 0) {
		adj[pos].erase(find(adj[pos].begin(), adj[pos].end(), par));
	}
	sze[pos] = 1;
	for (auto &j : adj[pos]) {
		dep[j] = 1 + dep[pos];
		dfs1(j, pos);
		sze[pos] += sze[j];
		if (sze[j] > sze[adj[pos][0]]) {
			swap(j, adj[pos][0]);
		}
	}
}
void dfs2 (int pos) {
	in[pos] = ++tt;
	for (auto j : adj[pos]) {
		nxt[j] = (j == adj[pos][0] ? nxt[pos] : j);
		dfs2(j);
	}
}
int highest[N];
#define mid ((l + r) >> 1)
#define tl (node << 1)
#define tr (node << 1 | 1)
struct SegmentTree {
	int tree[N << 2], lazy[N << 2];
	void prop (int l, int r, int node) {
		if (lazy[node] == 0) {
			return;
		}
		if (l != r) {
			for (auto x : {tl, tr}) {
				lazy[x] = lazy[node];
			}
		}
		tree[node] = lazy[node];
		lazy[node] = 0;
	}
	void update (int l, int r, int a, int b, int c, int node) {
		prop(l, r, node);
		if (l > b || r < a) return;
		if (l >= a && r <= b) {
			lazy[node] = c;
			prop(l, r, node);
			return;
		}
		update(l, mid, a, b, c, tl); update(mid + 1, r, a, b, c, tr);
	}
	int get (int l, int r, int a, int node) {
		prop(l, r, node);
		if (l == r) {
			return tree[node];
		}
		if (a <= mid) {
			return get(l, mid, a, tl);
		} else {
			return get(mid + 1, r, a, tr);
		}
	}
} cur;
void set_path (int u, int v, int w) {
	while (nxt[v] != nxt[u]) {
		cur.update(1, n, in[nxt[v]], in[v], w, 1);
		v = p[nxt[v]];
	}
	cur.update(1, n, in[u], in[v], w, 1);
}
int lca (int x, int y) {
	if (dep[x] > dep[y]) {
		swap(x, y);
	}
	for (int i = B - 1; i >= 0; i--) {
		if ((dep[y] - dep[x]) & (1 << i)) {
			y = dp[i][y];
		}
	}
	if (x == y) {
		return x;
	}
	for (int i = B - 1; i >= 0; i--) {
		if (dp[i][x] != dp[i][y]) {
			x = dp[i][x], y = dp[i][y];
		}
	}
	return p[x];
}
int main () {
	ios::sync_with_stdio(0); cin.tie(0);
	cin >> n >> m >> q;
	for (int i = 1; i < n; i++) {
		int a, b; cin >> a >> b;
		adj[a].push_back(b);
		adj[b].push_back(a);
	}
	dfs1(1, 0);
	nxt[1] = 1;
	dfs2(1);
	for (int i = 1; i <= m; i++) {
		cin >> a[i];
	}
	for (int i = 1; i <= q; i++) {
		int l, r; cin >> l >> r;
		queries[r].push_back({l, i});
	}
	for (int i = 1; i <= n; i++) {
		cur.update(1, n, in[i], in[i], -1, 1);
	}
	memset(highest, -1, sizeof(highest));
	vector <int> pp(m + 1, 0);
	vector <int> mxs, mns;
	for (int i = 1; i <= m; i++) {
		while (!mxs.empty() && in[a[mxs.back()]] < in[a[i]]) {
			mxs.pop_back();
		}
		mxs.push_back(i);
		while (!mns.empty() && in[a[mns.back()]] > in[a[i]]) {
			mns.pop_back();
		}
		mns.push_back(i);
		int u = a[i];
		while (true) {
			int z = cur.get(1, n, in[u], 1);
			if (z == -1) {
				if (u == 1) {
					break;
				}
				u = p[u];
				continue;
			}
			int y = highest[z];
			pp[z] -= (dep[u] - dep[y] + 1);
			if (a[z] == u) {
				highest[z] = -1;
			} else {
				int x = a[z];
				for (int j = B - 1; j >= 0; j--) {
					if (dp[j][x] != 0 && dep[dp[j][x]] > dep[u]) {
						x = dp[j][x];
					}
				}
				highest[z] = x;
			}
			if (y == 1) {
				break;
			}
			u = p[y];
		}	
		set_path(1, a[i], i);
		highest[i] = 1;
		pp[i] += dep[a[i]] + 1;
		for (auto [x, y] : queries[i]) {
			auto g = *lower_bound(mns.begin(), mns.end(), x);
			auto f = *lower_bound(mxs.begin(), mxs.end(), x);
			g = a[g]; f = a[f];
			int z = lca(g, f);
			ans[y] -= dep[z];
			for (int j = x; j <= i; j++) {
				ans[y] += pp[j];
			}
		}
	}
	for (int i = 1; i <= q; i++) {
		cout << ans[i] << '\n';
	}
}	

#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...