题意:
给定一棵树,节点有黑白两种颜色,有正负的边权。
有两种操作:
一种是修改反转某个节点的颜色;
另一种是询问树上最远的两个白色节点的距离。
思路:
树剖+堆维护的代码还是没敢去码。。以后再补了。。
这里用边分治+堆来维护。
边分治的优点比起点分支来说,优点就是每次分治之后,只有两个分支,处理起来比较简单,代码比较好写。缺点就是需要添加虚点,常数比较大。
边分治就是先添加虚点,使得每个节点的度数小于等于3,添加虚点的方法很容易看懂。
边分治就是选在当前分治结构里面选一条边,使得边的两端最大联通块尽可能的小。
对于一个分治结构,假设找到的分治的边为x-y,对于这个分治结构中的路径只有两种,不经过边x-y的和经过边x-y的,前者由子分治结构来考虑,现在只考虑后者。可以对边x-y两端分别维护两个大顶堆,堆里面放的是白色节点距离x的距离或者白色节点距离y的距离。所以经过x-y的最大路径就是两个堆的最大值加上x-y的边权。但是有修改操作,我们可以在堆里面再维护一个值,就是节点号x,如果堆顶的节点是黑色的话,说明这个节点已经不能用了,要pop掉。所以对每个节点要维护它所在的每一个分治结构,并且记录它是在分支结构的哪一边,更新的时候要沿着分治结构自底向上更新,最后询问的时候就是O(1),更新是O(lognlogn)。
#include<iostream>
#include<string>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#include<set>
#include<algorithm>
using namespace std;
#define LL long long
#define eps 1e-8
#define MP make_pair
#define N 200020
#define M 400020
#define NLGN 400002
#pragma comment(linker, "/STACK:1024000000,1024000000")
#define ls (i << 1)
#define rs (ls | 1)
#define md ((ll + rr) >> 1)
#define lson ll, md, ls
#define rson md + 1, rr, rs
#define mod 258280327
#define inf 0x3f3f3f3f
#define pii pair<int, int>
#define ULL unsigned long long
int readint() {
char c;
while((c = getchar()) && !(c >= '0' && c <= '9') && c != '-');
int ret = c - '0', sgn = 0;
if(c == '-') sgn = 1, ret = 0;
while((c = getchar()) && c >= '0' && c <= '9')
ret = ret * 10 + c - '0';
if(sgn) ret = -ret;
return ret;
}
char buf[8000000],*pt = buf,*o = buf;
int getint(){
int f = 1,x = 0;
while((*pt != '-') && (*pt < '0' || *pt > '9')) pt ++;
if(*pt == '-') f = -1,pt ++; else x = *pt++ - 48;
while(*pt >= '0' && *pt <= '9') x = x * 10 + *pt ++ - 48;
return x * f;
}
char getch(){
char ch;
while(*pt < 'A' || *pt > 'Z') pt ++;
ch=*pt;pt++;
return ch;
}
struct node {
int x, v;
node() {}
node(int x, int v):x(x), v(v) {};
bool operator < (const node &b) const {
return v < b.v;
}
};
struct P {
int p, t, d;
P() {}
P(int p, int t, int d): p(p), t(t), d(d) {}
};
vector<P> vt[N];
vector<node> g[N];
int n, fst[N], nxt[M], vv[M], cost[M], e;
bool del[M];
int tot, cnt, sz[N];
void init() {
memset(fst, -1, sizeof fst);
e = 0;
}
void add(int u, int v, int c) {
del[e] = 0, vv[e] = v, nxt[e] = fst[u], cost[e] = c, fst[u] = e++;
del[e] = 0, vv[e] = u, nxt[e] = fst[v], cost[e] = c, fst[v] = e++;
}
vector<node> t;
int mx[NLGN], cc[NLGN], LC[NLGN], RC[NLGN];
priority_queue<node> q[NLGN][2];
priority_queue<node> Q;
int ans;
bool col[N];
void dfs(int u, int p) {
int fa = 0;
for(int i = 0; i < g[u].size(); ++i) {
int v = g[u][i].x;
if(v == p) continue;
if(fa == 0) {
add(u, v, g[u][i].v);
fa = u;
}
else {
int k = ++tot;
add(fa, k, 0);
add(k, v, g[u][i].v);
fa = k;
}
dfs(v, u);
}
}
void dfs1(int u, int p) {
sz[u] = 1;
for(int i = fst[u]; ~i; i = nxt[i]) {
int v = vv[i];
if(v == p || del[i]) continue;
dfs1(v, u);
sz[u] += sz[v];
}
}
pii dfs2(int u, int p, int tt) {
pii ret(inf, -1);
for(int i = fst[u]; ~i; i = nxt[i]) {
int v = vv[i];
if(v == p || del[i]) continue;
int x = max(sz[v], tt - sz[v]);
if(x < ret.first)
ret = MP(x, i);
pii t = dfs2(v, u, tt);
if(t.first < ret.first)
ret = t;
}
return ret;
}
void dfs3(int u, int p, int k, int t, int d) {
if(u >= 1 && u <= n) {
vt[u].push_back(P(k, t, d));
q[k][t].push(node(u, d));
}
for(int i = fst[u]; ~i; i = nxt[i]) {
int v = vv[i], c = cost[i];
if(v == p || del[i]) continue;
dfs3(v, u, k, t, d + c);
}
}
void update(int p) {
while(!q[p][0].empty()) {
if(col[q[p][0].top().x]) {
q[p][0].pop();
continue;
}
break;
}
while(!q[p][1].empty()) {
if(col[q[p][1].top().x]) {
q[p][1].pop();
continue;
}
break;
}
if(q[p][0].empty() || q[p][1].empty())
mx[p] = 0;
else
mx[p] = q[p][0].top().v + q[p][1].top().v + cc[p];
if(LC[p]) mx[p] = max(mx[p], mx[LC[p]]);
if(LC[p]) mx[p] = max(mx[p], mx[RC[p]]);
}
int calc(int u) {
dfs1(u, -1);
int id = dfs2(u, -1, sz[u]).second;
if(id == -1) return 0;
int x = vv[id], y = vv[id^1];
del[id] = del[id^1] = 1;
int t = ++cnt;
dfs3(x, -1, t, 0, 0);
dfs3(y, -1, t, 1, 0);
LC[t] = calc(x);
RC[t] = calc(y);
cc[t] = cost[id];
ans = max(ans, mx[t]);
update(t);
return t;
}
int main() {
// freopen("tt.txt", "r", stdin);
fread(buf,1,8000000,stdin);
while(1) {
n = getint();
init();
for(int i = 1; i < n; ++i) {
int u, v, c;
u = getint();
v = getint();
c = getint();
g[u].push_back(node(v, c));
g[v].push_back(node(u, c));
}
tot = n;
dfs(1, -1);
ans = 0;
calc(1);
int qq;
qq = getint();
int node_cnt = n;
while(qq--) {
char s[10];
int u;
s[0] = getch();
if(s[0] == 'A') {
if(node_cnt == 0) {
puts("They have disappeared.");
}
else
printf("%d\n", max(0, mx[1]));
continue;
}
u = getint();
if(col[u]) {
++node_cnt;
col[u] = 0;
for(int i = vt[u].size() - 1; i >= 0; --i) {
int p = vt[u][i].p;
int t = vt[u][i].t;
int d = vt[u][i].d;
q[p][t].push(node(u, d));
update(p);
}
}
else {
--node_cnt;
col[u] = 1;
for(int i = vt[u].size() - 1; i >= 0; --i) {
int p = vt[u][i].p;
update(p);
}
}
}
}
return 0;
}