http://www.lydsy.com/JudgeOnline/problem.php?id=2325
吐槽一下部分分数据不满足性质
我打了6k的暴力..
考虑一条链的情况
记录8个值
m[0/1][0/1]表示左边从哪里开始走 右边从哪里开始走(上面还是下面) 最多是多少
l[0/1] r[0/1]表示左边右边最多延伸多少 gss1的套路
然后大力树剖一发 小心各种细节
复杂度\(O(m \log n ^ 2)\)
#include<bits/stdc++.h>
#define int long long
#define out(x) cerr << #x << " = " << x << "\n"
#define type(x) __typeof((x).begin())
#define foreach(it, x) for(type(x) it = (x).begin(); it != (x).end(); ++ it)
using namespace std;
// by piano
template<typename tp> inline void read(tp &x) {
x = 0; char c = getchar(); bool f = 0;
for(; c < '0' || c > '9'; f |= (c == '-'), c = getchar());
for(; c >= '0' && c <= '9'; x = (x << 3) + (x << 1) + c - '0', c = getchar());
if(f) x = -x;
}
template<typename tp> inline void arr(tp *a, int n) {
for(int i = 1; i <= n; i ++)
cout << a[i] << " ";
puts("");
}
#define P pair<int, int>
#define MP make_pair
#define mid (l + (r - l) / 2)
#define ls (rt << 1)
#define rs (rt << 1 | 1)
#define root 1, n, 1
const int N = 1e5 + 233;
const int inf = 1e8 + 233;
struct E {
int nxt, from, to;
}e[N << 1];
int head[N], e_cnt = 0;
char str[233];
inline void add(int u, int v) {
e[++ e_cnt] = (E) {head[u], u, v}; head[u] = e_cnt;
}
inline int cp(int a, int b) {
return a > b ? a : b;
}
int n, m;
struct seg {
int m00, m10, m01, m11;
int l0, l1;
int r0, r1;
inline void ovo(void) {
printf("%d %d %d %d\n", m00, m10, m01, m11);
printf("%d %d %d %d\n", l0, l1, r0, r1);
}
inline void clear(void) {
m00 = m10 = m01 = m11 = l0 = l1 = r0 = r1 = 0;
}
};
seg operator + (seg a, seg b) {
seg c;
c.m00 = cp(a.m00 + b.m00, a.m01 + b.m10);
c.m01 = cp(a.m00 + b.m01, a.m01 + b.m11);
c.m10 = cp(a.m10 + b.m00, a.m11 + b.m10);
c.m11 = cp(a.m10 + b.m01, a.m11 + b.m11);
c.l0 = cp(a.l0, cp(a.m00 + b.l0, a.m01 + b.l1));
c.l1 = cp(a.l1, cp(a.m10 + b.l0, a.m11 + b.l1));
c.r0 = cp(b.r0, cp(a.r0 + b.m00, a.r1 + b.m10));
c.r1 = cp(b.r1, cp(a.r0 + b.m01, a.r1 + b.m11));
return c;
}
namespace se {
seg tr[N << 2];
inline seg nw(void) {
if(str[1] == '#' && str[2] == '#')
return (seg) {-inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf};
if(str[1] == '.' && str[2] == '#')
return (seg) {1, -inf, -inf, -inf, 1, -inf, 1, -inf};
if(str[1] == '#' && str[2] == '.')
return (seg) {-inf, -inf, -inf, 1, -inf, 1, -inf, 1};
else
return (seg) {1, 2, 2, 1, 2, 2, 2, 2};
}
inline void upd(int l, int r, int rt, int L) {
if(l == r) {
tr[rt] = nw();
return ;
}
if(L <= mid) upd(l, mid, ls, L);
else upd(mid + 1, r, rs, L);
tr[rt] = tr[ls] + tr[rs];
}
inline seg query(int l, int r, int rt, int L, int R) {
if(L == l && r == R) {
return tr[rt];
}
if(R <= mid) return query(l, mid, ls, L, R);
else if(L > mid) return query(mid + 1, r, rs, L, R);
else return query(l, mid, ls, L, mid) + query(mid + 1, r, rs, mid + 1, R);
}
inline void debug(int l, int r, int rt) {
cout << l << " " << r << "\n";
tr[rt].ovo();
if(l == r)
return ;
debug(l, mid, ls);
debug(mid + 1, r, rs);
}
}
int dep[N], sz[N], fa[N], son[N], idx_cnt = 0, idx[N], top[N];
inline void dfs(int u, int fat) {
dep[u] = dep[fat] + 1;
sz[u] = 1; fa[u] = fat;
for(int i = head[u]; i; i = e[i].nxt) {
int v = e[i].to;
if(v != fat) {
dfs(v, u);
sz[u] += sz[v];
if(!son[u] || sz[son[u]] < sz[v])
son[u] = v;
}
}
}
inline void frt(int u, int tp) {
top[u] = tp; idx[u] = ++ idx_cnt;
if(son[u]) frt(son[u], tp);
for(int i = head[u]; i; i = e[i].nxt) {
int v = e[i].to;
if(v != fa[u] && v != son[u])
frt(v, v);
}
}
inline int L(seg &s) {
return cp(0, cp(s.l0, s.l1));
}
inline int R(seg &s) {
return cp(0, cp(s.r0, s.r1));
}
inline int Ans(seg &s) {
return cp(0, cp(cp(s.m00, s.m01), cp(s.m10, s.m11)));
}
inline seg rev(seg a) {
return (seg) {a.m00, a.m01, a.m10, a.m11, a.r0, a.r1, a.l0, a.l1};
}
inline int query(int u, int v) {
seg res1, res2;
res1.clear(); res2.clear();
while(top[u] != top[v]) {
// go v
if(dep[top[u]] < dep[top[v]]) {
seg now = se::query(root, idx[top[v]], idx[v]);
res2 = now + res2;
v = fa[top[v]];
}
// go u
else {
seg now = se::query(root, idx[top[u]], idx[u]);
res1 = now + res1;
u = fa[top[u]];
}
}
if(dep[u] < dep[v]) {
seg now = se::query(root, idx[u], idx[v]);
res2 = now + res2;
}
else {
seg now = se::query(root, idx[v], idx[u]);
res1 = now + res1;
}
res1 = rev(res1) + res2;
return L(res1);
}
main(void) {
read(n); read(m);
for(int i = 1; i <= n - 1; i ++) {
int x, y; read(x); read(y);
add(x, y); add(y, x);
}
dfs(1, 0); frt(1, 1);
for(int i = 1; i <= n; i ++) {
scanf("%s", str + 1);
se::upd(root, idx[i]);
}
for(int i = 1; i <= m; i ++) {
scanf("%s", str + 1);
if(str[1] == 'Q') {
int l, r;
read(l); read(r);
cout << query(l, r) << "\n";
}
else {
int id;
read(id); scanf("%s", str + 1);
se::upd(root, idx[id]);
}
}
}