具体解析不写了,直接放代码。
唉,AcWing 是这样的,又不默认给开 O2 时限还要从原题 4s 变成 3s。What can I say ? 只能开火车头了。
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-fstrict-overflow")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#include <stdio.h>
#include <algorithm>
#define getchar getchar_unlocked
#define putchar putchar_unlocked
int rd()
{
int k = 0, f = 1;
char c = getchar();
while (c < '0' || c > '9')
{
if (c == '-') f = 0;
c = getchar();
}
while (c >= '0' && c <= '9')
{
k = (k << 1) + (k << 3) + (c ^ 48);
c = getchar();
}
return f ? k : -k;
}
void wr(int x)
{
if (x < 0) putchar('-'), x = -x;
if (x > 9) wr(x / 10);
putchar((x % 10) ^ '0');
}
const int N = 100005;
const int INF = 2000000000;
// stack
int st[N << 1], top;
// tag & data
struct tag
{
int k, b; // mul, add (mul = 0 or 1)
tag(int _a = 1, int _b = 0) : k(_a), b(_b) {}
void modify(const tag &y) { k = y.k * k, b = y.k * b + y.b; }
};
struct dat
{
int mn, mx, sum, sz;
dat(int _mn = INF, int _mx = -INF, int _sum = 0, int _sz = 0) : mn(_mn), mx(_mx), sum(_sum), sz(_sz) {}
void modify(const tag &y)
{
mn = (mn < INF) ? y.k * mn + y.b : mn; // avoid null virson
mx = (mx > -INF) ? y.k * mx + y.b : mx;
sum = y.k * sum + y.b * sz;
}
dat operator+(const dat &y) const { return dat(std::min(mn, y.mn), std::max(mx, y.mx), sum + y.sum, sz + y.sz); };
};
// LCT
int rt;
int c[N << 1][2], fa[N << 1], root[N << 1];
tag real_tag[N << 1], vir_tag[N << 1];
dat sum_vir[N << 1], sum_real[N << 1], val[N << 1];
bool rev[N << 1];
int n, q;
void pushup(int x) // x > 0
{
if (x > n) val[x] = sum_vir[x - n] + sum_real[x - n];
sum_real[x] = sum_real[c[x][0]] + val[x] + sum_real[c[x][1]];
if (x <= n) sum_vir[x] = sum_vir[c[x][0]] + sum_real[root[x]] + sum_vir[c[x][1]];
}
void tag_real(const tag &x, int p) { if (p) sum_real[p].modify(x), val[p].modify(x), real_tag[p].modify(x); }
void tag_vir(const tag &x, int p) { if (p) sum_vir[p].modify(x), vir_tag[p].modify(x); }
void dorev(int x) { if (x) std::swap(c[x][0], c[x][1]), rev[x] ^= 1; }
void pushdown(int x) // x > 0
{
if (x > n) tag_real(real_tag[x], x - n), tag_vir(real_tag[x], x - n);
if (rev[x]) dorev(c[x][0]), dorev(c[x][1]), rev[x] ^= 1;
tag_real(real_tag[x], c[x][0]), tag_real(real_tag[x], c[x][1]), real_tag[x] = tag();
if (x <= n)
tag_vir(vir_tag[x], c[x][0]), tag_vir(vir_tag[x], c[x][1]), tag_real(vir_tag[x], root[x]), vir_tag[x] = tag();
}
bool isroot(int x) { return c[fa[x]][0] != x && c[fa[x]][1] != x; }
void rotate(int x)
{
int y = fa[x], z = fa[y], l = (c[y][0] != x), r = !l;
if (!isroot(y)) c[z][c[z][0] != y] = x;
fa[x] = z, fa[y] = x, fa[c[x][r]] = y, c[y][l] = c[x][r], c[x][r] = y;
pushup(y), pushup(x);
}
void splay(int x);
void del(int x, int y);
void ins(int x, int y);
void pushdownall(int x)
{
int tx = x;
while (!isroot(tx)) tx = fa[tx];
if (tx <= n && fa[tx]) del(fa[tx], tx);
tx = x;
st[top = 1] = tx;
while (!isroot(tx)) tx = fa[tx], st[++top] = tx;
while (top) pushdown(st[top--]);
}
void splay(int x)
{
pushdownall(x);
while (!isroot(x))
{
int y = fa[x], z = fa[y];
if (!isroot(y)) rotate(((c[y][0] == x) ^ (c[z][0] == y)) ? x : y);
rotate(x);
}
if (x <= n && fa[x]) ins(fa[x], x);
}
void del(int x, int y)
{
if (!y) return;
splay(y + n), fa[c[y + n][0]] = fa[c[y + n][1]] = 0;
if (c[y + n][0])
{
int p = c[y + n][0];
while (c[p][1]) pushdown(p), p = c[p][1];
splay(p), c[p][1] = c[y + n][1], fa[c[y + n][1]] = p, pushup(p), root[x] = p;
}
else root[x] = c[y + n][1];
c[y + n][0] = c[y + n][1] = 0, pushup(y + n), pushup(x);
}
void ins(int x, int y)
{
if (!y) return;
if (!root[x]) pushup(y + n), root[x] = y + n;
else
{
int p = root[x];
while (c[p][1]) pushdown(p), p = c[p][1];
splay(p), c[p][1] = y + n, fa[y + n] = p, pushup(y + n), pushup(p), root[x] = p;
}
pushup(x);
}
int access(int x)
{
int y = 0;
for (; x; y = x, x = fa[x]) splay(x), del(x, y), ins(x, c[x][1]), c[x][1] = y, pushup(x);
return y;
}
void makeroot(int x) { access(x), splay(x), dorev(x); }
int findroot(int x) // x is root
{
access(x), splay(x);
while (c[x][0]) pushdown(x), x = c[x][0];
return splay(x), x;
}
int findfa(int x)
{
makeroot(rt), access(x), splay(x);
x = c[x][0];
if (!x) return x;
while (c[x][1]) pushdown(x), x = c[x][1];
return splay(x), x;
}
void changert(int _rt) { rt = _rt; }
int lca(int x, int y) { return access(x), access(y); }
void split(int x, int y) { makeroot(x), access(y), splay(y); }
void init_pos(int x, int v) { val[x] = dat(v, v, v, 1), pushup(x), pushup(x + n); }
void updsubtree(int x, tag p) { split(rt, x), tag_real(p, root[x]), val[x].modify(p), pushup(x); }
dat querysubtree(int x) { return split(rt, x), sum_real[root[x]] + val[x]; }
void updchain(int x, int y, tag p) { split(x, y), tag_real(p, y); }
dat querychain(int x, int y) { return split(x, y), sum_real[y]; }
void link(int x, int y) { split(x, y), fa[x] = y, ins(y, x); } // assume findroot(x) ^ y
void cut(int x, int y) { split(x, y), c[y][0] = fa[x] = 0, pushup(y); } // assume c[y][0] == x && !c[x][1]
void changefa(int x, int y)
{
if (!(x ^ rt)) return;
int z = findfa(x);
cut(x, z);
makeroot(x), access(y), splay(y);
link(x, findroot(y) == x ? z : y);
}
int u[N << 1], v[N << 1];
int main()
{
n = rd(), q = rd();
for (int i = 1; i < n; i++) u[i] = rd(), v[i] = rd();
for (int i = 1; i <= n; i++) init_pos(i, rd());
for (int i = 1; i < n; i++) link(u[i], v[i]);
changert(rd());
int op = 0, x = 0, y = 0, z = 0;
while (q--)
{
op = rd();
switch (op)
{
case 0:
x = rd(), y = rd(), updsubtree(x, tag(0, y));
break;
case 1:
x = rd(), changert(x);
break;
case 2:
x = rd(), y = rd(), z = rd(), updchain(x, y, tag(0, z));
break;
case 3:
x = rd(), wr(querysubtree(x).mn), putchar('\n');
break;
case 4:
x = rd(), wr(querysubtree(x).mx), putchar('\n');
break;
case 5:
x = rd(), y = rd(), updsubtree(x, tag(1, y));
break;
case 6:
x = rd(), y = rd(), z = rd(), updchain(x, y, tag(1, z));
break;
case 7:
x = rd(), y = rd(), wr(querychain(x, y).mn), putchar('\n');
break;
case 8:
x = rd(), y = rd(), wr(querychain(x, y).mx), putchar('\n');
break;
case 9:
x = rd(), y = rd(), changefa(x, y);
break;
case 10:
x = rd(), y = rd(), wr(querychain(x, y).sum), putchar('\n');
break;
default:
x = rd(), wr(querysubtree(x).sum), putchar('\n');
break;
}
}
}