#include <iostream>
#include <cstring>
#include <algorithm>
#include <bitset>
#include <vector>
#define endl '\n'
#define int long long
#define inf 0x3f3f3f3f
#define lnf 0x3f3f3f3f3f3f3f3f
using namespace std;
//#define gc() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 20, stdin), p1 == p2) ? EOF : *p1 ++)
//char *p1, *p2, buf[(1 << 20) + 5];
//
//inline int read() {
// int x = 0;
// char c = gc();
//
// while (!isdigit(c)) {
// c = gc();
// }
//
// while (isdigit(c)) {
// x = (x << 3) + (x << 1) + (c ^ 48);
// c = gc();
// }
//
// return x;
//}
//
//void write(int k) {
// if (k > 9) {
// write(k / 10);
// }
//
// putchar(k % 10 + 48);
//}
//
const int N = 4e5;
void init();
int n, m, opt, u, c, in[N + 5], l[N + 5], r[N + 5], cnt;
vector<int> son[N + 5];
struct Segment_Tree {
int mid;
struct Tree_Node {
int l, r, flag;
bitset<64> val;
} tr[(N << 2) + 5];
void Push_Up(int k) {
tr[k].val = tr[k << 1].val | tr[k << 1 | 1].val;
}
void Push_Down(int k) {
if (tr[k].flag) {
tr[k].val.reset();
tr[k].val[tr[k].flag] = 1;
tr[k << 1].flag = tr[k << 1 | 1].flag = tr[k].flag;
tr[k << 1].val.reset();
tr[k << 1 | 1].val.reset();
tr[k << 1].val[tr[k].flag] = tr[k << 1 | 1].val[tr[k].flag] = 1;
tr[k].flag = 0;
}
}
void Build(int k, int l, int r) {
// cout << "Build:k=" << k << ",l=" << l << ",r=" << r << ";\n";
tr[k].l = l;
tr[k].r = r;
tr[k].flag = 0;
tr[k].val.reset();
if (l == r) {
tr[k].val[in[l]] = 1;
return;
}
mid = (l + r) >> 1;
Build(k << 1, l, mid);
Build(k << 1 | 1, mid + 1, r);
Push_Up(k);
}
void Section_Edit(int k, int l, int r, int x) {
if (tr[k].r < l || tr[k].l > r) {
return;
}
cout << "Section_Edit:k=" << k << ",l=" << l << ",r=" << r << ",x=" << x << ",tr[k].l=" << tr[k].l << ",tr[k].r=" << tr[k].r << ";\n";
if (l <= tr[k].l && tr[k].r <= r) {
tr[k].flag = x;
return;
}
mid = (l + r) >> 1;
Push_Down(k);
if (l <= mid) {
Section_Edit(k << 1, l, r, x);
}
if (r > mid) {
Section_Edit(k << 1 | 1, l, r, x);
}
Push_Up(k);
}
bitset<64> Section_Inquire(int k, int l, int r) {
bitset<64> ans;
ans.reset();
if (tr[k].r < l || tr[k].l > r) {
return ans;
}
// cout << "Section_Inquire:k=" << k << ",l=" << l << ",r=" << r << ",tr[k].l=" << tr[k].l << ",tr[k].r=" << tr[k].r << ";\n";
//
if (l <= tr[k].l && tr[k].r <= r) {
return tr[k].val;
}
ans.reset();
mid = (l + r) >> 1;
Push_Down(k);
if (l <= mid) {
ans |= Section_Inquire(k << 1, l, r);
}
if (r > mid) {
ans |= Section_Inquire(k << 1 | 1, l, r);
}
return ans;
}
} a;
void DFS(int k) {
l[k] = ++ cnt;
// cout << "DFS:k=" << k << ",cnt=" << cnt << ";\n";
for (auto it : son[k]) {
// cout << "DFS_son:it=" << it << ",k=" << k << ",son[k][it]=" << son[k][it] << ";\n";
DFS(it);
}
r[k] = cnt;
// cout << "DFS_lr:k=" << k << ",l[k]=" << l[k] << ",r[k]=" << r[k] << ";\n";
}
signed main() {
init();
cin >> n >> m;
// n = read();
// m = read();
for (int i = 1; i <= n; ++ i) {
cin >> in[i];
// in[i] = read();
}
a.Build(1, 1, n);
for (int i = 1; i < n; ++ i) {
cin >> u >> c;
// u = read();
// c = read();
son[u].push_back(c);
}
DFS(1);
while (m --) {
cin >> opt >> u;
// opt = read();
// u = read();
if (opt == 1) {
cin >> c;
// c = read();
a.Section_Edit(1, l[u], r[u], c);
} else {
cout << a.Section_Inquire(1, l[u], r[u]).count() << endl;
// write(a.Section_Inquire(1, l[u], r[u]).count());
// puts("");
}
}
return 0;
}
void init() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
}
代码重构以后就AC了,但是还是很疑惑这到底哪里错了。