历时两天A掉此题,特作纪念。
#include
typedef long long LL;
#define FOR(i, a, b) for (int i = (a), i##_END_ = (b); i <= i##_END_; i++)
#define DNF(i, a, b) for (int i = (a), i##_END_ = (b); i >= i##_END_; i--)
template void in(Tp &x) {
char ch = getchar(), f = 1; x = 0;
while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
if (ch == '-') f = -1, ch = getchar();
while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar();
x *= f;
}
template bool chkmax(Tp &x, Tp y) {return x > y ? 0 : (x=y,1);}
template bool chkmin(Tp &x, Tp y) {return x < y ? 0 : (x=y,1);}
template Tp Max(Tp x, Tp y) {return x > y ? x : y;}
template Tp Min(Tp x, Tp y) {return x < y ? x : y;}
const int MAXN = 200010;
struct Tag {
int k, b;
Tag(int k = 1, int b = 0): k(k), b(b) {}
Tag run(const Tag &another) const {
return Tag(k * another.k, b * another.k + another.b);
}
};
struct Data {
int minx, maxx, sum, sz;
Data(int sz = 0, int minx = 0x3f3f3f3f, int maxx = -0x3f3f3f3f, int sum = 0)
:minx(minx), maxx(maxx), sum(sum), sz(sz) {}
Data run(const Tag &another) const {
if (minx > maxx) return *this;
Data ret;
ret.sum = sum * another.k + sz * another.b;
ret.sz = sz;
if (another.k < 0) {
ret.minx = another.k * maxx + another.b;
ret.maxx = another.k * minx + another.b;
}
else {
ret.maxx = another.k * maxx + another.b;
ret.minx = another.k * minx + another.b;
}
return ret;
}
Data run(const Data &another) const {
Data ret;
if (minx > maxx) return another;
if (another.minx > another.minx) return *this;
ret.sz = sz + another.sz;
ret.sum = sum + another.sum;
ret.minx = Min(minx, another.minx);
ret.maxx = Max(maxx, another.maxx);
return ret;
}
};
struct Node {
bool inner;
bool is_rev;
Node *ch[4], *fa;
Tag tag_chain, tag_sub;
Data data_chain, data_sub, data_all, my;
void pushdown();
void update();
void add();
void del();
void push();
void pushO();
void pushI();
void splayO();
void splayI();
void rotate(int);
void access(bool=false);
bool is_top_out();
bool is_top_inn();
void makerot();
void push_rev();
void push_tag_chain(Tag);
void push_tag_sub(Tag);
} *to[MAXN];
int n, m, rt;
int input[MAXN][2], w[MAXN];
int debug(Node *x)
{
FOR(i, 1, n) if (x == to[i]) return i;
return 0;
}
void Node::pushO()
{
assert(!inner);
if (!is_top_out()) fa -> pushO();
pushdown();
}
void Node::pushI()
{
//if (!inner) return;
assert(inner);
if (!is_top_inn()) fa -> pushI();
pushdown();
}
void initialize()
{
FOR(i, 1, n) {
to[i] = new Node;
to[i] -> ch[0] = to[i] -> ch[1] =
to[i] -> ch[2] = to[i] -> ch[3] = NULL;
to[i] -> fa = NULL;
to[i] -> inner = false;
to[i] -> is_rev = false;
to[i] -> tag_chain = to[i] -> tag_sub = Tag();
to[i] -> data_chain = to[i] -> data_sub = Data();
to[i] -> my = Data(1, w[i], w[i], w[i]);
to[i] -> data_all =
to[i] -> my.run(to[i] -> data_chain).run(to[i] -> data_sub);
}
}
void Node::push()
{
if (fa) fa -> push(); pushdown();
}
bool Node::is_top_out()
{
return !fa || fa -> ch[0] != this && fa -> ch[1] != this;
}
bool Node::is_top_inn()
{
//printf("%d %d\n", inner, fa);
//printf("%d\n", fa != NULL);
return !fa -> inner;
}
void Node::add()
{
Node *tmp = fa;
while (tmp -> ch[3] != NULL && (tmp -> inner || tmp == fa)) {
tmp -> pushdown();
tmp = tmp -> ch[3];
}
if (tmp != fa) assert(!tmp -> inner);
if (tmp == fa) tmp -> ch[3] = this;
else {
tmp -> fa -> ch[3] = new Node;
Node *&x = tmp -> fa -> ch[3];
x -> inner = true;
x -> is_rev = false;
x -> fa = tmp -> fa;
x -> ch[0] = x -> ch[1] = NULL;
x -> ch[2] = tmp; x -> ch[3] = this;
tmp -> fa = fa = x;
Node *tep = x;
while (tep -> inner) {
tep -> update(); tep = tep -> fa;
}
x -> splayI();
}
}
void Node::del()
{
int t = fa -> ch[2] == this ? 2 : 3;
if (fa -> ch[t] != this) {
assert(fa -> ch[t] == this);
}
if (fa -> inner) {
// Node *tt = fa;
fa -> pushI();
Node *bro = fa -> ch[t ^ 1];
bro -> fa = fa -> fa;
int tt = bro -> fa -> ch[2] == fa ? 2 : 3;
assert(bro -> fa -> ch[tt] == fa);
bro -> fa -> ch[tt] = bro;
Node *tep = bro -> fa;
while (tep -> inner) {
tep -> update(); tep = tep -> fa;
}
if (bro -> fa -> inner)
bro -> fa -> splayI();
delete fa;
}
else {
fa -> pushdown();
fa -> ch[t] = NULL;
}
}
//不负责update,只负责pushdown
void Node::access(bool is)
{
push();
splayO(); pushdown();
if (ch[1] != NULL) ch[1] -> add();
ch[1] = NULL; update();
Node *x = this;
while (x -> fa != NULL) {
Node *tmp = x -> fa;
while (tmp -> inner) tmp = tmp -> fa;
if (!is) x -> del();
else is = false;
//while (tmp -> inner) tmp = tmp -> fa;
tmp -> splayO(); tmp -> pushdown();
if (tmp -> ch[1] != NULL) tmp -> ch[1] -> add();
x -> fa = tmp;
tmp -> ch[1] = x; tmp -> update();
x = tmp;
}
}
void Node::rotate(int dir)
{
Node *pa = fa; fa = pa -> fa;
if (fa != NULL) {
int t = (fa -> ch[0] == pa ? 0 :
(fa -> ch[1] == pa ? 1 : (fa -> ch[2] == pa ? 2 : 3)));
fa -> ch[t] = this;
}
pa -> ch[dir] = ch[dir ^ 1];
if (ch[dir ^ 1] != NULL) ch[dir ^ 1] -> fa = pa;
ch[dir ^ 1] = pa; pa -> fa = this;
pa -> update(); update();
}
void Node::splayO()
{
assert(!inner);
pushO();
while (!is_top_out()) {
int t1 = fa -> ch[0] == this ? 0 : 1;
if (!fa -> is_top_out()) {
int t2 = fa -> fa -> ch[0] == fa ? 0 : 1;
if (t1 == t2) fa -> rotate(t1), rotate(t1);
else rotate(t1), rotate(t2);
}
else rotate(t1);
}
}
void Node::splayI()
{
assert(inner);
pushI();
while (!is_top_inn()) {
int t1 = fa -> ch[2] == this ? 2 : 3;
if (!fa -> is_top_inn()) {
int t2 = fa -> fa -> ch[2] == fa ? 2 : 3;
if (t1 == t2) fa -> rotate(t1), rotate(t1);
else rotate(t1), rotate(t2);
}
else rotate(t1);
}
}
void Node::push_rev()
{
is_rev ^= 1;
std::swap(ch[0], ch[1]);
}
void Node::push_tag_chain(Tag x)
{
tag_chain = tag_chain.run(x);
my = my.run(x);
data_chain = data_chain.run(x);
data_all = my.run(data_sub).run(data_chain);
}
void Node::push_tag_sub(Tag x)
{
tag_sub = tag_sub.run(x);
//tag_chain = tag_chain.run(x);
//my = my.run(x);
data_sub = data_sub.run(x);
//data_chain = data_chain.run(x);
data_all = my.run(data_sub).run(data_chain);
}
void Node::update()
{
data_sub = Data();
if (ch[0] != NULL) data_sub = data_sub.run(ch[0] -> data_sub);
if (ch[1] != NULL) data_sub = data_sub.run(ch[1] -> data_sub);
if (ch[2] != NULL) data_sub = data_sub.run(ch[2] -> data_all);
if (ch[3] != NULL) data_sub = data_sub.run(ch[3] -> data_all);
data_chain = Data();
if (ch[0] != NULL)
data_chain = data_chain.run(ch[0] -> data_chain).run(ch[0] -> my);
if (ch[1] != NULL)
data_chain = data_chain.run(ch[1] -> data_chain).run(ch[1] -> my);
data_all = my.run(data_sub).run(data_chain);
}
void Node::pushdown()
{
if (is_rev) {
if (ch[0] != NULL) ch[0] -> push_rev();
if (ch[1] != NULL) ch[1] -> push_rev();
is_rev = false;
}
{
Tag &tag = tag_chain;
if (tag.k != 1 || tag.b != 0) {
if (ch[0] != NULL) ch[0] -> push_tag_chain(tag);
if (ch[1] != NULL) ch[1] -> push_tag_chain(tag);
tag = Tag(1, 0);
}
}
{
Tag &tag = tag_sub;
if (tag.k != 1 || tag.b != 0) {
if (ch[0] != NULL) ch[0] -> push_tag_sub(tag);
if (ch[1] != NULL) ch[1] -> push_tag_sub(tag);
if (ch[2] != NULL) {
ch[2] -> push_tag_chain(tag);
ch[2] -> push_tag_sub(tag);
}
if (ch[3] != NULL) {
ch[3] -> push_tag_chain(tag);
ch[3] -> push_tag_sub(tag);
}
tag = Tag(1, 0);
}
}
}
void Node::makerot()
{
access(); splayO(); push_rev();
}
void link(Node *x, Node *y)
{
y -> access(); y -> pushdown();
x -> makerot(); x -> fa = y; x -> access(true);
}
void cut(Node *x, Node *y)
{
x -> makerot(); y -> access(); y -> splayO();
y -> pushdown(); x -> fa = y -> ch[0] = NULL; y -> update();
}
Node *find_rot(Node *x)
{
x -> access(); x -> splayO(); x -> pushdown();
while (x -> ch[0] != NULL) {
x = x -> ch[0]; x -> pushdown();
}
return x;
}
int main()
{
in(n); in(m);
FOR(i, 1, n - 1) {
in(input[i][0]); in(input[i][1]);
}
FOR(i, 1, n) in(w[i]);
initialize();
in(rt);
FOR(i, 1, n - 1) {
link(to[input[i][0]], to[input[i][1]]);
}
FOR(i, 1, m) {
int tp; in(tp);
to[rt] -> makerot();
//FOR(i, 1, n)
// to[i] -> access();
//to[rt] -> splayO();
//printf("%d\n", to[rt] -> data_all.sz);
if (tp == 0) {
int x, y; in(x); in(y);
to[x] -> access(); to[x] -> splayO();
if (x == rt) {
to[x] -> push_tag_chain(Tag(0, y));
to[x] -> push_tag_sub(Tag(0, y));
}
else {
to[x] -> my = to[x] -> my.run(Tag(0, y));
if (to[x] -> ch[3] != NULL) {
to[x] -> ch[3] -> push_tag_chain(Tag(0, y));
to[x] -> ch[3] -> push_tag_sub(Tag(0, y));
}
if (to[x] -> ch[2] != NULL) {
to[x] -> ch[2] -> push_tag_chain(Tag(0, y));
to[x] -> ch[2] -> push_tag_sub(Tag(0, y));
}
to[x] -> update();
}
}
else if (tp == 1) {
int x; in(x); rt = x;
}
else if (tp == 2) {
int x, y, z; in(x); in(y); in(z);
to[x] -> makerot(); to[y] -> access(); to[y] -> splayO();
to[y] -> push_tag_chain(Tag(0, z));
}
else if (tp == 3) {
int x; in(x); to[x] -> access();
Data ret = Data();
if (to[x] -> ch[2] != NULL) ret = ret.run(to[x] -> ch[2] -> data_all);
if (to[x] -> ch[3] != NULL) ret = ret.run(to[x] -> ch[3] -> data_all);
ret = ret.run(to[x] -> my);
printf("%d\n", ret.minx);
}
else if (tp == 4) {
int x; in(x); to[x] -> access();
Data ret = Data();
if (to[x] -> ch[2] != NULL) ret = ret.run(to[x] -> ch[2] -> data_all);
if (to[x] -> ch[3] != NULL) ret = ret.run(to[x] -> ch[3] -> data_all);
ret = ret.run(to[x] -> my);
printf("%d\n", ret.maxx);
}
else if (tp == 5) {
int x, y; in(x); in(y);
to[x] -> access(); to[x] -> splayO();
if (x == rt) {
to[x] -> push_tag_chain(Tag(1, y));
to[x] -> push_tag_sub(Tag(1, y));
}
else {
to[x] -> my = to[x] -> my.run(Tag(1, y));
if (to[x] -> ch[2] != NULL) {
to[x] -> ch[2] -> push_tag_chain(Tag(1, y));
to[x] -> ch[2] -> push_tag_sub(Tag(1, y));
}
if (to[x] -> ch[3] != NULL) {
to[x] -> ch[3] -> push_tag_chain(Tag(1, y));
to[x] -> ch[3] -> push_tag_sub(Tag(1, y));
}
to[x] -> update();
}
}
else if (tp == 6) {
int x, y, z; in(x); in(y); in(z);
to[x] -> makerot(); to[y] -> access(); to[y] -> splayO();
to[y] -> push_tag_chain(Tag(1, z));
}
else if (tp == 7) {
int x, y; in(x); in(y);
to[x] -> makerot(); to[y] -> access(); to[y] -> splayO();
printf("%d\n", to[y] -> my.run(to[y] -> data_chain).minx);
}
else if (tp == 8) {
int x, y; in(x); in(y);
to[x] -> makerot(); to[y] -> access(); to[y] -> splayO();
printf("%d\n", to[y] -> my.run(to[y] -> data_chain).maxx);
}
else if (tp == 9) {
int x, y; in(x); in(y);
to[y] -> access(); to[x] -> access();
to[x] -> splayO(); to[x] -> pushdown();
if (to[x] -> ch[0] == NULL) continue;
else {
to[y] -> access(); to[y] -> splayO();
Node *tmp = to[x];
while (!tmp -> is_top_out()) tmp = tmp -> fa;
if (tmp == to[y]) continue;
to[x] -> access(); to[x] -> splayO(); to[x] -> pushdown();
tmp = to[x] -> ch[0]; tmp -> pushdown();
while (tmp -> ch[1] != NULL) {tmp = tmp -> ch[1]; tmp -> pushdown();}
cut(to[x], tmp); link(to[x], to[y]);
}
}
else if (tp == 10) {
int x, y; in(x); in(y);
to[x] -> makerot(); to[y] -> access(); to[y] -> splayO();
printf("%d\n", to[y] -> my.run(to[y] -> data_chain).sum);
}
else if (tp == 11) {
int x; in(x); to[x] -> access(); //to[x] -> splayO();
Data ret = Data();
if (to[x] -> ch[2] != NULL) ret = ret.run(to[x] -> ch[2] -> data_all);
if (to[x] -> ch[3] != NULL) ret = ret.run(to[x] -> ch[3] -> data_all);
ret = ret.run(to[x] -> my);
printf("%d\n", ret.sum);
}
}
return 0;
}