比赛 |
树形数据结构拔高 |
评测结果 |
AAAAAAAAAAAAATTTTTTT |
题目名称 |
滑稽♂树 |
最终得分 |
65 |
用户昵称 |
LikableP |
运行时间 |
36.512 s |
代码语言 |
C++ |
内存使用 |
5.98 MiB |
提交时间 |
2025-04-17 21:59:43 |
显示代码纯文本
#include <cstdio>
#define DEBUG 1 // 调试开关
struct IO {
#define MAXSIZE (1 << 20)
#define isdigit(x) (x >= '0' && x <= '9')
char buf[MAXSIZE], *p1, *p2;
char pbuf[MAXSIZE], *pp;
#if DEBUG
#else
IO() : p1(buf), p2(buf), pp(pbuf) {}
~IO() { fwrite(pbuf, 1, pp - pbuf, stdout); }
#endif
char gc() {
#if DEBUG // 调试,可显示字符
return getchar();
#endif
if (p1 == p2) p2 = (p1 = buf) + fread(buf, 1, MAXSIZE, stdin);
return p1 == p2 ? ' ' : *p1++;
}
bool blank(char ch) {
return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t';
}
template <class T>
void read(T &x) {
double tmp = 1;
bool sign = false;
x = 0;
char ch = gc();
for (; !isdigit(ch); ch = gc())
if (ch == '-') sign = 1;
for (; isdigit(ch); ch = gc()) x = x * 10 + (ch - '0');
if (ch == '.')
for (ch = gc(); isdigit(ch); ch = gc())
tmp /= 10.0, x += tmp * (ch - '0');
if (sign) x = -x;
}
void read(char *s) {
char ch = gc();
for (; blank(ch); ch = gc());
for (; !blank(ch); ch = gc()) *s++ = ch;
*s = 0;
}
void read(char &c) { for (c = gc(); blank(c); c = gc()); }
void push(const char &c) {
#if DEBUG // 调试,可显示字符
putchar(c);
#else
if (pp - pbuf == MAXSIZE) fwrite(pbuf, 1, MAXSIZE, stdout), pp = pbuf;
*pp++ = c;
#endif
}
template <class T>
void write(T x) {
if (x < 0) x = -x, push('-'); // 负数输出
static T sta[35];
T top = 0;
do {
sta[top++] = x % 10, x /= 10;
} while (x);
while (top) push(sta[--top] + '0');
}
template <class T>
void write(T x, char lastChar) {
write(x), push(lastChar);
}
} io;
const int MAXN = 3e4 + 10;
const int MAXV = 1e4;
int n, q;
int a[MAXN];
int fa[MAXN];
struct EDGE {
int v, next;
EDGE (){};
EDGE (int v, int next) : v(v), next(next) {};
} edge[MAXN << 1];
int head[MAXN], edgeNum;
void AddEdge(int u, int v) {
edge[++edgeNum] = EDGE(v, head[u]);
head[u] = edgeNum;
}
struct ValueSegmentTree {
struct NODE {
int ls, rs;
int sum;
} node[MAXN * 20];
int nodeNum, root[MAXN];
int cnt;
void Init() {
for (int i = 1; i <= nodeNum; ++i) node[i].ls = node[i].rs = node[i].sum = 0;
for (int i = 1; i <= cnt; ++i) root[i] = 0;
nodeNum = 0;
cnt = 0;
}
void Insert(int rootBefore, int &root, int lt, int rt, int x, int val) {
root = ++nodeNum;
node[root] = node[rootBefore];
if (lt == rt) {
node[root].sum += val;
return ;
}
int mid = lt + ((rt - lt) >> 1);
if (x <= mid) {
Insert(node[rootBefore].ls, node[root].ls, lt, mid, x, val);
} else {
Insert(node[rootBefore].rs, node[root].rs, mid + 1, rt, x, val);
}
node[root].sum = node[node[root].ls].sum + node[node[root].rs].sum;
}
int GetK(int rootBefore, int root, int lt, int rt, int k) {
if (lt == rt) {
return lt;
}
int mid = lt + ((rt - lt) >> 1);
int x = node[node[root].ls].sum - node[node[rootBefore].ls].sum;
if (x >= k) {
return GetK(node[rootBefore].ls, node[root].ls, lt, mid, k);
} else {
return GetK(node[rootBefore].rs, node[root].rs, mid + 1, rt, k - x);
}
}
void dfs(int now, int fa) {
++cnt;
Insert(root[cnt - 1], root[cnt], 1, MAXV, a[now], 1);
for (int i = head[now]; i; i = edge[i].next) {
if (edge[i].v == fa) continue;
dfs(edge[i].v, now);
}
}
};
struct SegmentTree {
struct node{
int ls, rs;
int sum;
} node[MAXN * 20];
int nodeNum, root;
void Init() {
for (int i = 1; i <= nodeNum; ++i) node[i].ls = node[i].rs = node[i].sum = 0;
root = 0;
nodeNum = 0;
}
void Insert(int &root, int lt, int rt, int x, int val) {
if (!root) root = ++nodeNum;
if (lt == rt) {
node[root].sum += val;
return ;
}
int mid = lt + ((rt - lt) >> 1);
if (x <= mid) {
Insert(node[root].ls, lt, mid, x, val);
} else {
Insert(node[root].rs, mid + 1, rt, x, val);
}
node[root].sum = node[node[root].ls].sum + node[node[root].rs].sum;
}
int GetSum(int root, int lt, int rt, int lq, int rq) {
if (root == 0 || root > nodeNum) return 0;
if (lt == lq && rt == rq) return node[root].sum;
int mid = lt + ((rt - lt) >> 1);
if (rq <= mid) {
return GetSum(node[root].ls, lt, mid, lq, rq);
} else if (lq > mid) {
return GetSum(node[root].rs, mid + 1, rt, lq, rq);
} else {
return GetSum(node[root].ls, lt, mid, lq, mid) + GetSum(node[root].rs, mid + 1, rt, mid + 1, rq);
}
}
void dfs(int now, int fa) {
Insert(root, 1, MAXV, a[now], 1);
for (int i = head[now]; i; i = edge[i].next) {
if (edge[i].v == fa) continue;
dfs(edge[i].v, now);
}
}
};
void dfs(int root, int fa) { // 找父亲
::fa[root] = fa;
for (int i = head[root]; i; i = edge[i].next) {
if (edge[i].v == fa) continue;
dfs(edge[i].v, root);
}
}
ValueSegmentTree ST0, ST;
SegmentTree ST00, STT;
int main() {
freopen("hjtree.in", "r", stdin);
freopen("hjtree.out", "w", stdout);
io.read(n);
for (int i = 1; i <= n; ++i) {
io.read(a[i]);
}
for (int i = 1; i <= n - 1; ++i) {
int u, v;
io.read(u), io.read(v);
AddEdge(u, v);
AddEdge(v, u);
}
dfs(1, 0);
ST0.Init();
ST0.dfs(1, 0);
ST00.Init();
ST00.dfs(1, 0);
io.read(q);
while (q--) {
int opt, u, k, a, b, x;
io.read(opt);
if (opt == 1) {
io.read(u), io.read(k);
if (u == 1) {
io.write(ST0.GetK(ST0.root[0], ST0.root[ST0.cnt], 1, MAXV, k), '\n');
} else {
ST.Init();
ST.dfs(u, fa[u]);
io.write(ST.GetK(ST.root[0], ST.root[ST.cnt], 1, MAXV, k), '\n');
}
} else if (opt == 2) {
io.read(u), io.read(a), io.read(b);
if (u == 1) {
io.write(ST00.GetSum(ST00.root, 1, MAXV, a, b), '\n');
} else {
STT.Init();
STT.dfs(u, fa[u]);
io.write(STT.GetSum(STT.root, 1, MAXV, a, b), '\n');
}
} else {
io.read(u), io.read(x);
::a[u] = x;
ST0.Init();
ST00.Init();
ST0.dfs(1, 0);
ST00.dfs(1, 0);
}
}
return 0;
}