Submission #1269912

#TimeUsernameProblemLanguageResultExecution timeMemory
1269912_filya_Synchronization (JOI13_synchronization)C++20
0 / 100
2353 ms38272 KiB
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int N = 1e5 + 50, logN = 30;

struct segtree {
 
	vector<long long> lazy, sum;
	int size = 1;
 
	void init(int n) {
		while (size < n) {
			size *= 2;
		}
		lazy.assign(2 * size - 1, 0ll);
		sum.assign(2 * size - 1, 0ll);
	}
 
	void prop(int x, int lx, int rx) {
		if (rx - lx == 1) {
			lazy[x] = 0;
			return;
		}
		lazy[2 * x + 1] += lazy[x];
		lazy[2 * x + 2] += lazy[x];
		sum[2 * x + 1] += lazy[x] * static_cast<long long>(rx - lx) / 2;
		sum[2 * x + 2] += lazy[x] * static_cast<long long>(rx - lx) / 2;
		lazy[x] = 0;
	}
 
	void add(int l, int r, ll v, int x, int lx, int rx) {
		if (lx >= l && rx <= r) {
			lazy[x] += v;
			sum[x] += v * static_cast<long long>(rx - lx);
			return;
		}
		if (rx <= l || lx >= r) {
			return;
		}
		int m = (rx + lx) / 2;
		add(l, r, v, 2 * x + 1, lx, m);
		add(l, r, v, 2 * x + 2, m, rx);
		sum[x] = sum[2 * x + 1] + sum[2 * x + 2] + lazy[x] * (rx - lx);
	}
 
	void add(int l, int r, ll val) {
		add(l, r, val, 0, 0, size);
	}
 
	ll query(ll l, ll r, int x, ll lx, ll rx) {
		prop(x, lx, rx);
		if (lx >= l && rx <= r) {
			return sum[x];
		}
		if (rx <= l || lx >= r) {
			return 0ll;
		}
		int m = (rx + lx) / 2;
		ll s1 = query(l, r, 2 * x + 1, lx, m);
		ll s2 = query(l, r, 2 * x + 2, m, rx);
		return s1 + s2 + lazy[x] * (rx - lx);
	}
 
	ll query(ll l, ll r) {
		return query(l, r, 0, 0, size);
	}
} tree1, tree2;

int last[N], ans[N], par[N], root[N], depth[N], sz[N], pos[N], rpos[N], anc[N][logN + 1], ti = 0; 
vector<int> G[N];

void dfsSz(int s, int p) {
    sz[s] = 1;
    depth[s] = depth[p] + 1;
    par[s] = p;
    if (root[s] == -1) root[s] = s;
    for (auto& u : G[s]) {
        if (u == p) continue;
        dfsSz(u, s);
        sz[s] += sz[u];
        if (sz[u] > sz[G[s][0]]) swap(G[s][0], u);
    }
}

void dfsHld(int s, int p) {
    pos[s] = ++ti;
    rpos[ti] = s;
    for (auto u : G[s]) {
        if (u == p) continue;
        root[u] = (u == G[s][0] ? root[s] : u);
        dfsHld(u, s);
    }
}

// int highest_ancesor(int u) {
//     if (tree1.query(pos[root[u]], pos[u] + 1) == pos[u] - pos[root[u]]) {
//         return root[u];
//     } 
//     if (tree1.query(pos[u], pos[u] + 1) == 0) {
//         return u;
//     } 
//     int l = pos[root[u]] - 1, r = pos[u];
//     while(r - l > 1) {
//         int mid = (r + l + 1) / 2;
//         if (tree1.query(mid, pos[u] + 1) != pos[u] - mid) {
//             l = mid;
//         } else {
//             r = mid;
//         }
//     }
//     return rpos[r];
// }

// void query1(int u) {
//     int s = u;
//     int dif = tree2.query(pos[s], pos[s] + 1) - last[s];
//     while(s != -1) {
//         int h = highest_ancesor(s);
//         tree2.add(pos[h], pos[s] + 1 - (s == u), dif);
//         if (h != root[s] || !h || tree1.query(pos[h], pos[s] + 1) != pos[s] - pos[h] + 1) {
//             break;
//         }
//         s = par[root[s]];
//     }
// }

// int query2(int s) {
//     while(s != -1) {
//         int h = highest_ancesor(s);
//         if (h != root[s] || !h || tree1.query(pos[h], pos[s] + 1) != pos[s] - pos[h] + 1) {
//             return h;
//         }
//         s = par[root[s]];
//     }
//     return 0;
// }

int kth_ancesor(int u, int k) {
	for (int pow = 0; pow <= logN; pow++) {
		if ((k & (1 << pow)) != 0) {
			u = anc[u][pow];
			if (u == -1) break;
		}
	}
	return u;
}

int query1(int u, int v) {
	int res = 0;
	for (; root[u] != root[v]; v = par[root[v]]) {
		if (depth[root[u]] > depth[root[v]]) swap(u, v);
		res += tree1.query(pos[root[v]], pos[v] + 1);
	}
	if (depth[u] > depth[v]) swap(u, v);
    res += tree1.query(pos[u] + 1, pos[v] + 1);
	return res;
}

void query2(int u, int v) {
	int dif = tree2.query(pos[u], pos[u] + 1) - last[u];
	u = par[u];
	for (; root[u] != root[v]; v = par[root[v]]) {
		if (depth[root[u]] > depth[root[v]]) swap(u, v);
		tree2.add(pos[root[v]], pos[v] + 1, dif);
	}
	if (depth[u] > depth[v]) swap(u, v);
	tree2.add(pos[u], pos[v] + 1, dif);
}

int highest_ancesor(int u) {
	int l = 0, r = depth[u];
	while(r - l > 1) {
		int mid = (r + l) / 2;
		int v = kth_ancesor(u, mid);
		if (v == -1 || query1(u, v) < depth[u] - depth[v]) {
			r = mid;
		} else {
			l = mid;
		}
	}
	int res = kth_ancesor(u, l);
	return (res == -1 ? u : res);
}

int highest_ancesor2(int u) {
	while(tree1.query(pos[u], pos[u] + 1)) {
		u = par[u];
	}
	return u;
}

int main()
{
// 	ifstream cin("input.txt");
//     ofstream cout("output.txt");
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);
	srand(time(nullptr));
	int n, m, q; cin >> n >> m >> q;
    vector<array<int, 2>> edges;
    for (int i = 0; i < n - 1; i++) {
        int u, v; cin >> u >> v;
        u--; v--;
        G[u].push_back(v);
        G[v].push_back(u);
        edges.push_back({u, v});
    }
    dfsSz(0, -1);
    dfsHld(0, -1);
	anc[0][0] = -1;
	for (int i = 0; i < n; i++) anc[i][0] = par[i];
	for (int j = 1; j <= logN; j++) {
        anc[0][j] = -1;
        for (int i = 1; i < n; i++) {
            if (anc[i][j - 1] == -1) {
                anc[i][j] = -1;
                continue;
            }
            anc[i][j] = anc[anc[i][j - 1]][j - 1];
        }
    }
    tree1.init(n + 1);
    tree2.init(n + 1);
    for (int i = 0; i < n; i++) {
        ans[i] = 1;
        last[i] = 0;
        tree2.add(pos[i], pos[i] + 1, 1);
    }
    for (auto& e : edges) {
        if (e[0] == par[e[1]]) swap(e[0], e[1]);
    }
    while(m--) {
        int e; cin >> e; e--;
        auto [u, v] = edges[e];
        if (tree1.query(pos[u], pos[u] + 1) == 0) {
            tree1.add(pos[u], pos[u] + 1, 1);
            query2(u, highest_ancesor(u));
        } else {
            int anc = highest_ancesor(u);
            last[u] = tree2.query(pos[u], pos[u] + 1);
            ll pl = tree2.query(pos[anc], pos[anc] + 1) - last[u];
            tree2.add(pos[u], pos[u] + 1, pl);
            tree1.add(pos[u], pos[u] + 1, -1);
        }
		// int cool = 0;
		// for (int i = 0; i < n; i++) {
		// 	if (highest_ancesor(i) != highest_ancesor2(i)) {
		// 		cool = i + 1;
		// 	}
		// }
		// if (!cool) cout << "Cool\n";
		// else cout << "Bad " << cool << '\n';
    }
    while(q--) {
        int u; cin >> u; u--;
        int anc = highest_ancesor(u);
        cout << tree2.query(pos[anc], pos[anc] + 1) << '\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...