- 一棵 (n) 个点的无根树,每个点有颜色 (1) 或 (2),初始颜色均为 (1),每条边有边权。
- 两个点在同一个联通块,当且仅当,两点间路径上的所有点的颜色相同。
- (m) 次操作,询问一个点所在联通块直径或修改一条链上点为同一种颜色。
- (n, m leq 10^5)。
TopTree
#include <bits/stdc++.h>
#define dbg(...)
std::cerr << " 33[32;1m", fprintf(stderr, __VA_ARGS__),
std::cerr << " 33[0m"
template <class T, class U>
inline bool smin(T &x, const U &y) {
return y < x ? x = y, 1 : 0;
}
template <class T, class U>
inline bool smax(T &x, const U &y) {
return x < y ? x = y, 1 : 0;
}
using LL = long long;
using PII = std::pair<int, int>;
inline char gc() {
static constexpr int BufferSize = 1 << 22 | 5;
static char buf[BufferSize], *p, *q;
static std::streambuf *i = std::cin.rdbuf();
return p == q ? p = buf, q = p + i->sgetn(p, BufferSize), p == q ? EOF : *p++ : *p++;
}
inline void pc(char c) {
static std::streambuf *o = std::cout.rdbuf();
o->sputc(c);
}
template <class T>
inline void readInt(T &w) {
char c, p = 0;
while (!isdigit(c = gc())) p = c == '-';
for (w = c & 15; isdigit(c = gc());) w = w * 10 + (c & 15);
if (p) w = -w;
}
template <class T, class... U>
inline void readInt(T &w, U &... a) {
readInt(w), readInt(a...);
}
template <class T>
inline void printInt(T w) {
static char c[50], *p;
if (w < 0) pc('-'), w = -w;
if (w == 0) return pc('0');
for (p = c; w; w /= 10) *++p = w % 10;
while (p != c) pc(*p-- | '0');
pc('
');
}
constexpr int N(1e5 + 5);
struct VertexInfo {
int c;
VertexInfo() : c(0) {}
void update(int x) { c = x; }
};
struct RakeInfo {
std::array<int, 2> ld, lans;
RakeInfo() { ld[0] = ld[1] = lans[0] = lans[1] = 0; }
RakeInfo rake(RakeInfo a) {
RakeInfo r;
for (int i = 0; i < 2; i++) {
r.ld[i] = std::max(ld[i], a.ld[i]);
r.lans[i] = std::max({lans[i], a.lans[i], ld[i] + a.ld[i]});
}
return r;
}
} rNull;
struct ClusterInfo : RakeInfo {
std::array<int, 2> rd, rans, pld, prd, pans;
std::array<bool, 2> pc;
int len;
ClusterInfo() : len(0) {
rd[0] = rd[1] = rans[0] = rans[1] = pld[0] = pld[1] = prd[0] = prd[1] =
pans[0] = pans[1] = 0;
pc[0] = pc[1] = true;
}
ClusterInfo &base(int x) {
len = x;
return *this;
}
void reverse() {
std::swap(ld, rd);
std::swap(lans, rans);
std::swap(pld, prd);
}
void update(int x) {
if (pc[0] && pc[1]) return;
pc[x] = true, pc[!x] = false;
ld[x] = pld[x];
rd[x] = prd[x];
lans[x] = rans[x] = pans[x];
ld[!x] = rd[!x] = lans[!x] = rans[!x] = 0;
}
ClusterInfo &compress(ClusterInfo a, ClusterInfo b, RakeInfo m,
VertexInfo x) {
int c = x.c;
pc[c] = a.pc[c] && b.pc[c];
pc[!c] = false;
len = a.len + b.len;
ld = a.ld, lans = a.lans;
rd = b.rd, rans = b.rans;
if (a.pc[c]) {
int l = std::max(m.ld[c], b.ld[c]);
smax(ld[c], a.len + l);
smax(lans[c], ld[c]);
smax(lans[c], a.rd[c] + l);
smax(lans[c], m.ld[c] + b.ld[c]);
smax(lans[c], m.lans[c]);
smax(lans[c], b.lans[c]);
}
if (b.pc[c]) {
int r = std::max(m.ld[c], a.rd[c]);
smax(rd[c], b.len + r);
smax(rans[c], rd[c]);
smax(rans[c], b.ld[c] + r);
smax(rans[c], m.ld[c] + a.rd[c]);
smax(rans[c], m.lans[c]);
smax(rans[c], a.rans[c]);
}
for (int i = 0; i < 2; i++) {
pld[i] = std::max({a.pld[i], a.len + b.pld[i], a.len + m.ld[i]});
prd[i] = std::max({b.prd[i], b.len + a.prd[i], b.len + m.ld[i]});
pans[i] = std::max({a.pans[i], b.pans[i], m.lans[i], a.prd[i] + b.pld[i],
a.prd[i] + m.ld[i], m.ld[i] + b.pld[i]});
}
return *this;
}
} cNull;
struct SplayTree {
SplayTree *ch[3], *fa;
SplayTree() { ch[0] = ch[1] = ch[2] = fa = nullptr; }
bool nrt() const { return fa && (fa->ch[0] == this || fa->ch[1] == this); }
bool dir() const { return fa->ch[1] == this; }
void sch(int d, SplayTree *c) {
ch[d] = c;
if (c) c->fa = this;
}
void rotate() {
SplayTree *p = fa;
bool d = dir();
fa = p->fa;
if (fa) {
fa->ch[fa->ch[2] == p ? 2 : p->dir()] = this;
}
p->sch(d, ch[!d]), sch(!d, p);
p->pushup();
}
void update() {
if (nrt()) fa->update();
pushdown();
}
void splay() {
for (update(); nrt(); rotate()) {
if (fa->nrt()) {
(fa->dir() == dir() ? fa : this)->rotate();
}
}
pushup();
}
virtual void pushup() {}
virtual void pushdown() {}
virtual ~SplayTree() {}
};
#define cch(i) static_cast<CompressTree *>(ch[i])
#define rch(i) static_cast<RakeTree *>(ch[i])
struct RakeTree : SplayTree {
RakeInfo rInfo;
void pushup();
};
struct CompressTree : SplayTree {
bool rev;
int tag;
ClusterInfo cInfo;
VertexInfo vInfo;
CompressTree() : rev(false), tag(-1), cInfo(), vInfo() {}
void pushup();
void reverse() {
rev = !rev;
std::swap(ch[0], ch[1]);
cInfo.reverse();
}
void update(int x) {
tag = x;
vInfo.update(x);
cInfo.update(x);
}
void pushdown() {
if (rev) {
if (ch[0]) cch(0)->reverse();
if (ch[1]) cch(1)->reverse();
rev = false;
}
if (tag != -1) {
if (ch[0]) cch(0)->update(tag);
if (ch[1]) cch(1)->update(tag);
tag = -1;
}
}
void access() {
splay();
if (ch[1]) {
auto r = new RakeTree;
r->sch(0, ch[2]), r->sch(2, ch[1]), r->pushup();
ch[1] = nullptr, sch(2, r), pushup();
}
for (; fa; rotate()) {
fa->splay();
SplayTree *m = fa, *p = m->fa;
assert(p);
p->splay();
m->pushdown();
if (p->ch[1]) {
m->sch(2, p->ch[1]);
m->pushup();
} else {
if (!m->ch[0]) {
p->sch(2, m->ch[1]);
} else if (!m->ch[1]) {
p->sch(2, m->ch[0]);
} else {
auto x = m->ch[0];
x->fa = nullptr;
while (x->pushdown(), x->ch[1]) x = x->ch[1];
x->splay();
p->sch(2, x);
x->sch(1, m->ch[1]);
x->pushup();
}
delete m;
}
p->sch(1, this);
}
pushup();
}
void evert() { access(), reverse(), pushdown(); }
};
inline void RakeTree::pushup() {
auto &a = ch[0] ? rch(0)->rInfo : rNull;
auto &b = ch[1] ? rch(1)->rInfo : rNull;
auto &c = ch[2] ? cch(2)->cInfo : cNull;
rInfo = a.rake(c.rake(b));
}
inline void CompressTree::pushup() {
auto &a = ch[0] ? cch(0)->cInfo : cNull;
auto &b = ch[1] ? cch(1)->cInfo : cNull;
auto &c = ch[2] ? rch(2)->rInfo : rNull;
cInfo.compress(a, b, c, vInfo);
}
CompressTree *link(CompressTree *x, CompressTree *y, int len) {
x->access(), y->evert();
auto e = new CompressTree;
e->cInfo.base(len);
x->sch(1, y), y->sch(0, e);
y->pushup(), x->pushup();
return x;
}
int main() {
double sta = (double)clock() / CLOCKS_PER_SEC;
int n, m;
readInt(n);
CompressTree *t = new CompressTree[n + 1];
std::vector<int> p(n);
for (int i = 1; i < n; i++) readInt(p[i]);
for (int i = 1, x; i < n; i++) {
readInt(x);
auto r = t + i + 1;
link(t + p[i], t + i + 1, x);
}
readInt(m);
while (m--) {
int opt, x, y, z;
readInt(opt, x);
if (opt == 1) {
t[x].access();
int d = t[x].cInfo.rans[t[x].vInfo.c];
if (d) {
printInt(d);
} else {
pc('Q'), pc('w'), pc('Q'), pc('
');
}
} else {
readInt(y, z);
t[x].evert(), t[y].access();
t[y].update(z - 1);
}
}
dbg("time : %.5f
", (double)clock() / CLOCKS_PER_SEC - sta);
return 0;
}