1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
|
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cstdarg> #include <set> #define debug(x) cerr << #x << " = " << x << endl #define debugf(...) fprintf(stderr, __VA_ARGS__) #define debugs(x) fputs(x"\n", stderr) using namespace std; template <class T> bool cmax(T &a, T b) { return b > a ? (a = b, 1) : 0; } template <class T> bool cmin(T &a, T b) { return b < a ? (a = b, 1) : 0; } template <class T> void read(T &a) { a = 0; char c = getchar(); int f = 0; while (!isdigit(c)) { f ^= c == '-', c = getchar(); } while (isdigit(c)) { a = a * 10 + (c ^ 48), c = getchar(); } a *= f ? -1 : 1; } struct Fastin { template <class T> Fastin& operator >> (T &x) {read(x); return *this;} } fastin;
#define int long long
const int MAXN = 2e5 + 10;
template <typename T, int n> class binary_indexed_tree { T c[n + 10]; public: void add(int p, T v) { p++; for (; p <= n; p += p & -p) c[p] += v; } T query(int p) { p++; T v = 0; for (; p; p -= p & -p) v += c[p]; return v; } T range(int l, int r) { return (r >= l) ? query(r) - query(l - 1) : 0; } };
int n, q; int in[MAXN], out[MAXN], id[MAXN], siz[MAXN]; set <int> pos[MAXN]; binary_indexed_tree <int, MAXN> a, b;
class Graph { int tot = 0, head[MAXN] = {0}, dfx = 0; struct Edge { int to; int next; } e[MAXN << 1] = {0}; public: void addEdge(int x, int y) { tot++; e[tot].to = y; e[tot].next = head[x]; head[x] = tot; } int dfs(int u, int f) { in[u] = ++dfx; id[in[u]] = u; siz[u] = 1; for (int i = head[u], v; i; i = e[i].next) { v = e[i].to; if (v == f) continue; siz[u] += dfs(v, u); } out[u] = ++dfx; return siz[u]; } } G;
void add(int p, int d) { a.add(in[p], d), a.add(out[p] + 1, -d); b.add(in[p], siz[p] * d); }
int mid = 0; void modify(int p, int c) { auto it = pos[c].upper_bound(in[p]); if (it != pos[c].begin() && out[id[*prev(it)]] >= out[p]) { return; } while (it != pos[c].end() && *it <= out[p]) { add(id[*it], -1); it = pos[c].erase(it); } add(p, 1); pos[c].insert(in[p]); }
int qid = 0; int query(int p) { return a.range(1, in[p]) * siz[p] + b.range(in[p] + 1, out[p] - 1); }
signed main() { fastin >> n >> q; for (int i = 1, x, y; i < n; i++) { fastin >> x >> y; G.addEdge(x, y); G.addEdge(y, x); } G.dfs(1, 0); for (int i = 1, op, x, c; i <= q; i++) { fastin >> op; if (op == 1) { fastin >> x >> c; modify(x, c); } else { fastin >> x; cout << query(x) << endl; } } return 0; }
|