给出一棵树,和3种操作:
1.更改第i条边的权值;
2.更改结点a到结点b所有边的权值为负;
2.查询结点a到结点b所有边的权值的最大值.
把一颗树hash成一维,在数组中,重链上的点一定是连续存储的.作为边剖分型,可以把边挂在儿子结点上,转化成点剖分型.
另外还要注意的时,最后更新至两条路已经更新至拥有LCA时,由于边的特点,LCA(所代表的那条边)不能更新,所以要更新至LCA的下一个重儿子.但是这样会导致一个问题,可能两个点是同一个点,即LCA.这个时候在线段树里面要特判一下.
#include
#include
#include
#include
#include
#include
using namespace std;
#define MAXN 10010
#define INF 0x7ffffff
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
int sz[MAXN], dep[MAXN], son[MAXN], fa[MAXN], top[MAXN], totw;
int c[MAXN], p[MAXN], w[MAXN], rw[MAXN];
char op[12];
struct Edge
{
int v, id, next;
}ee[MAXN << 1];
int pre[MAXN], tote;
inline void Init()
{
memset(pre, 0, sizeof(pre));
top[1] = fa[1] = sz[1] = 1;
dep[1] = sz[0] = tote = totw = 0;
}
inline void addedge(int u, int v, int id)
{
tote++;
ee[tote].v = v;
ee[tote].id = id;
ee[tote].next = pre[u];
pre[u] = tote;
}
void dfs1(int i = 1)
{
sz[i] = 1, son[i] = 0;
for(int j = pre[i]; j; j = ee[j].next) if(ee[j].v != fa[i])
{
int v = ee[j].v;
fa[v] = i;
p[v] = ee[j].id;
dep[v] = dep[i] + 1;
dfs1(v);
sz[i] += sz[v];
if(sz[v] > sz[son[i]]) son[i] = v;
}
}
void dfs2(int i = 1)
{
for(int j = pre[i]; j; j = ee[j].next) if(ee[j].v == son[i])
{
w[ee[j].id] = ++totw;
rw[totw] = ee[j].id;
top[son[i]] = top[i];
dfs2(son[i]);
break;
}
for(int j = pre[i]; j; j = ee[j].next) if(ee[j].v != fa[i] && ee[j].v != son[i])
{
w[ee[j].id] = ++totw;
rw[totw] = ee[j].id;
dfs2(top[ee[j].v] = ee[j].v);
}
}
int maxc[MAXN << 2], minc[MAXN << 2], rev[MAXN << 2];
void Build(int l = 1, int r = totw, int rt = 1)
{
rev[rt] = 0;
if(l >= r)
{
maxc[rt] = minc[rt] = c[rw[l]];
return ;
}
int m = (l + r) >> 1;
Build(lson), Build(rson);
maxc[rt] = max(maxc[rt << 1], maxc[rt << 1 | 1]);
minc[rt] = min(minc[rt << 1], minc[rt << 1 | 1]);
}
void Pushdown(int rt)
{
if(rev[rt])
{
rev[rt << 1] ^= 1, rev[rt << 1 | 1] ^= 1;
swap(maxc[rt << 1], minc[rt << 1]);
maxc[rt << 1] *= -1, minc[rt << 1] *= -1;
swap(maxc[rt << 1 | 1], minc[rt << 1 | 1]);
maxc[rt << 1 | 1] *= -1, minc[rt << 1 | 1] *= -1;
rev[rt] = 0;
}
}
int Query(int L, int R, int l = 1, int r = totw, int rt = 1)
{
if(L > R || R == 0) return -INF;
if(L <= l && r <= R) return maxc[rt];
Pushdown(rt);
int lch = -INF, rch = -INF;
int m = (l + r) >> 1;
if(L <= m) lch = Query(L, R, lson);
if(R > m) rch = Query(L, R, rson);
return max(lch, rch);
}
void Update(int p, int k, int l = 1, int r = totw, int rt = 1)
{
if(l >= r)
{
maxc[rt] = minc[rt] = k;
return ;
}
Pushdown(rt);
int m = (l + r) >> 1;
if(p <= m) Update(p, k, lson);
if(p > m) Update(p, k, rson);
maxc[rt] = max(maxc[rt << 1], maxc[rt << 1 | 1]);
minc[rt] = min(minc[rt << 1], minc[rt << 1 | 1]);
}
void Negate(int L, int R, int l = 1, int r = totw, int rt = 1)
{
if(L > R || R == 0) return ;
if(L <= l && r <= R)
{
rev[rt] ^= 1;
swap(maxc[rt], minc[rt]);
maxc[rt] *= -1, minc[rt] *= -1;
return ;
}
Pushdown(rt);
int m = (l + r) >> 1;
if(L <= m) Negate(L, R, lson);
if(R > m) Negate(L, R, rson);
maxc[rt] = max(maxc[rt << 1], maxc[rt << 1 | 1]);
minc[rt] = min(minc[rt << 1], minc[rt << 1 | 1]);
}
int main()
{
int t, n; scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
Init();
for(int i = 1; i < n; i++)
{
int u, v;
scanf("%d%d%d",&u,&v,&c[i]);
addedge(u, v, i);
addedge(v, u, i);
}
dfs1(), dfs2();
Build();
while(~scanf("%s", op))
{
if(op[0] == 'D') break;
if(op[0] == 'C')
{
int i, v;
scanf("%d%d", &i, &v);
Update(w[i], v);
}
else
{
int a, b, ans = -INF;
scanf("%d%d", &a, &b);
while(top[a] != top[b])
{
if(dep[top[a]] < dep[top[b]]) swap(a, b);
if(op[0] == 'Q') ans = max(ans, Query(w[p[top[a]]], w[p[a]]));
else Negate(w[p[top[a]]], w[p[a]]);
a = fa[top[a]];
}
if(dep[a] < dep[b]) swap(a, b);
if(op[0] == 'Q') ans = max(ans, Query(w[p[son[b]]], w[p[a]]));
else Negate(w[p[son[b]]], w[p[a]]);
if(op[0] == 'Q') printf("%d\n", ans);
}
}
}
return 0;
}