Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #define _CRT_SECURE_NO_WARNINGS
- #include <stdio.h>
- #include <cstdio>
- #include <cstdlib>
- #include <iostream>
- #include <sstream>
- #include <string>
- #include <unordered_map>
- #include <unordered_set>
- //#include <windows.h>
- #include <math.h>
- #include <algorithm>
- #include <bitset>
- #include <cassert>
- #include <climits>
- #include <ctime>
- #include <fstream>
- #include <functional>
- #include <iomanip>
- #include <locale>
- #include <map>
- #include <queue>
- #include <random>
- #include <set>
- #include <stack>
- #include <vector>
- using namespace std;
- #define forn(i, n) for (int i = 0; i < n; i++)
- #define what_is(x) cerr << '\n' << #x << " = " << x << '\n'
- #define print_arr(heh) cerr << '\n'; for (auto u : heh) cerr << u << ' '; cerr << '\n'
- #define print_arri(heh) cerr << '\n'; for (int i = 0; i < heh.size(); i++) cerr << #heh << "[" << i << "] = " << heh[i] << '\n'
- //#define endl '\n'
- #define all(a) a.begin(), a.end()
- //#define int long long
- #define ll long long
- #define ld long double
- #define DEBUG
- struct edge {
- int num;
- int distance;
- int ans;
- edge() {
- }
- edge(const int num, const int distance) : num(num), distance(distance) {
- }
- bool operator<(const edge& b) {
- return distance < b.distance;
- }
- };
- vector <vector <int>> g;
- vector <int> block;
- vector <int> treeSize;
- vector <int> centrPar;
- vector <bool> color;
- vector <int> ansWhite;
- vector <int> ansBlack;
- vector <int> countWhite;
- vector <int> countBlack;
- vector <int> whiteContribution;
- vector <int> blackContribution;
- vector <vector <edge>> centrEdges;
- vector <unordered_map<int, int>> distFromCentroid;
- int n, m;
- //dfs
- int calcSizes(int v, int p) {
- treeSize[v] = 1;
- for (auto u : g[v]) {
- if (u != p && !block[u])
- treeSize[v] += calcSizes(u, v);
- }
- return treeSize[v];
- }
- int findCentr(int v, int p, int n) {
- for (auto u : g[v]) {
- if (u != p && !block[u] && treeSize[u] * 2 > n) {
- return findCentr(u, v, n);
- }
- }
- return v;
- }
- void calcDistFromCentroid(int v, int p, int dist, vector <edge>& edges) {
- for (auto u : g[v]) {
- if (u != p && !block[u]) {
- edges.push_back(edge(u, dist + 1));
- calcDistFromCentroid(u, v, dist + 1, edges);
- }
- }
- }
- int calcContribution(int v, int p, int dist) {
- int curAns = dist;
- for (auto u : g[v]) {
- if (u != p && !block[u]) {
- curAns += calcContribution(u, v, dist + 1);
- }
- }
- return curAns;
- }
- void buildCentr(int v, int p, int contr) {
- int curSize = calcSizes(v, p);
- int centroid = findCentr(v, p, curSize);
- centrPar[centroid] = p;
- centrEdges[centroid].push_back(edge(centroid, 0));
- calcDistFromCentroid(centroid, -1, 0, centrEdges[centroid]);
- sort(all(centrEdges[centroid]));
- for (auto u : centrEdges[centroid]) {
- distFromCentroid[centroid][u.num] = u.distance;
- ansWhite[centroid] += u.distance;
- }
- countWhite[centroid] = centrEdges[centroid].size();
- whiteContribution[centroid] = contr;
- /*centrEdges[centroid][0].ans = centrEdges[centroid][0].num;
- for (size_t i = 1; i < centrEdges[centroid].size(); i++) {
- centrEdges[centroid][i].ans = min(centrEdges[centroid][i].num, centrEdges[centroid][i - 1].ans);
- }*/
- block[centroid] = 1;
- for (auto u : g[centroid]) {
- if (u != p && !block[u]) {
- int contr = calcContribution(u, -1, 1);
- buildCentr(u, centroid, contr);
- }
- }
- }
- void updateColor(int v, int start) {
- if (v == -1) return;
- if (color[start] == 0) {
- ansWhite[v] += distFromCentroid[v][start];
- ansBlack[v] -= distFromCentroid[v][start];
- countWhite[v]++;
- countBlack[v]--;
- if (centrPar[v] != -1) {
- whiteContribution[v] += distFromCentroid[centrPar[v]][start];
- blackContribution[v] -= distFromCentroid[centrPar[v]][start];
- }
- }
- else {
- ansWhite[v] -= distFromCentroid[v][start];
- ansBlack[v] += distFromCentroid[v][start];
- countWhite[v]--;
- countBlack[v]++;
- if (centrPar[v] != -1) {
- whiteContribution[v] -= distFromCentroid[centrPar[v]][start];
- blackContribution[v] += distFromCentroid[centrPar[v]][start];
- }
- }
- updateColor(centrPar[v], start);
- }
- ll getAns(int v, int p, int start) {
- if (v == -1) return 0;
- int d = distFromCentroid[v][start];
- if (color[start] == 0) {
- ll curAns = ansWhite[v] + d * countWhite[v];
- if (p != v) {
- curAns -= (whiteContribution[p] + d * countWhite[p]);
- }
- return curAns + getAns(centrPar[v], v, start);
- }
- else {
- ll curAns = ansBlack[v] + d * countBlack[v];
- if (p != v) {
- curAns -= (blackContribution[p] + d * countBlack[p]);
- }
- return curAns + getAns(centrPar[v], v, start);
- }
- }
- //#define TEST
- #ifdef TEST
- #include "testB3.h"
- #endif
- int32_t main() {
- ios::sync_with_stdio(0);
- cin.tie(0);
- cin >> n >> m;
- g.resize(n);
- block.resize(n);
- treeSize.resize(n);
- centrPar.resize(n);
- centrEdges.resize(n);
- distFromCentroid.resize(n);
- color.resize(n);
- ansBlack.resize(n);
- ansWhite.resize(n);
- countWhite.resize(n);
- countBlack.resize(n);
- whiteContribution.resize(n);
- blackContribution.resize(n);
- forn(i, n - 1) {
- int a, b;
- cin >> a >> b;
- a--; b--;
- g[a].push_back(b);
- g[b].push_back(a);
- }
- buildCentr(0, -1, 0);
- #ifdef TEST
- test();
- #endif
- forn(i, m) {
- int t, v;
- cin >> t >> v;
- v--;
- if (t == 1) {
- color[v] = !color[v];
- updateColor(v, v);
- }
- else {
- cout << getAns(v, v, v) << '\n';
- }
- }
- #ifdef DEBUG
- cerr << "\nTime: " << (double)clock() / CLOCKS_PER_SEC << endl;
- #endif
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement