// poj 3237 Tree 树链剖分
//
// 解题思路:
//
// 树链剖分,维护一个最大值和一个最小值,
// 区间更新,laz标记.单点更新,去掉叶子节点的laz
// 标记.边权改为离根节点较远的点的点权.求lca
// 的方式进行区间更新.注意线段树的操作以及push_up()
// push_down()的操作.写了很久,感悟颇多,继续加油吧~~~
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#define cls(x,a) memset(x,a,sizeof(x))
using namespace std;
const int MAXN = 10008;
const int INF = 0x7fffffff;
int n;
int num;
int id;
int idx[MAXN]; // 树上节点在线段树中的编号
int son[MAXN]; // 重儿子
int siz[MAXN]; // 以该节点为根的子树的节点数
int dep[MAXN]; // 节点的深度
int top[MAXN]; // 链的开头
int rk[MAXN]; // 与idx互逆的
int father[MAXN]; // 父节点
int head[MAXN];
int val[MAXN];
struct adj{
int to;
int next;
adj(){
}
adj(int a,int b):to(a),next(b){
}
}edges[MAXN<<1];
struct node {
int u;
int v;
int w;
node(){
}
node(int u,int v,int w):u(u),v(v),w(w){
}
}e[MAXN];
void add_edge(int u,int v){
edges[num] = adj(v,head[u]);
head[u] = num++;
}
void dfs(int u,int fa,int d){
dep[u] = d;
father[u] =fa;
son[u] = 0;
siz[u] = 1;
for (int i = head[u]; i + 1; i = edges[i].next){
int v = edges[i].to;
if (v == fa)
continue;
dfs(v,u,d+1);
siz[u] += siz[v];
if (siz[son[u]] < siz[v])
son[u] = v;
}
}
void dfs(int u,int tp){
top[u] = tp;
idx[u] = id++;
rk[idx[u]] = u;
if (son[u]) dfs(son[u],tp);
for (int i = head[u] ;i + 1 ;i = edges[i].next){
int v = edges[i].to;
if (v == father[u] || v == son[u])
continue;
dfs(v,v);
}
}
void input(){
id = 1;
num = 0;
cls(idx,0);
cls(father,0);
cls(son,0);
cls(head,-1);
scanf("%d",&n);
for (int i = 1;i < n;i ++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
e[i] = node(u,v,w);
add_edge(u,v);
add_edge(v,u);
}
}
#define lson(x) (x<<1) // 线段树部分
#define rson(x) (x<<1|1)
int vmax[MAXN<<2];
int vmin[MAXN<<2];
int laz[MAXN<<2];
int ql,qr;
int delta;
inline void update_node(int ro){
vmax[ro] *= -1;
vmin[ro] *= -1;
swap(vmin[ro],vmax[ro]);
}
inline void push_up(int ro){
vmax[ro] = max(vmax[lson(ro)],vmax[rson(ro)]);
vmin[ro] = min(vmin[lson(ro)],vmin[rson(ro)]);
}
inline void push_down(int ro,int L,int R){
if (L == R) return;
if (laz[ro]){
laz[lson(ro)] ^= 1;
laz[rson(ro)] ^= 1;
update_node(lson(ro));
update_node(rson(ro));
laz[ro] = 0;
}
}
void build(int ro,int L,int R){
laz[ro] = 0;
if (L == R){
vmax[ro] = val[L];
vmin[ro] = val[L];
return ;
}
int M = (L + R) >> 1;
build(lson(ro),L,M);
build(rson(ro),M+1,R);
push_up(ro);
}
void n_update(int ro,int L,int R){
if (ql<= L && R <= qr){
laz[ro] ^= 1;
update_node(ro);
return ;
}
push_down(ro,L,R);
int M = (L + R) >> 1;
if (ql <= M ) n_update(lson(ro),L,M);
if (M < qr) n_update(rson(ro),M+1,R);
push_up(ro);
}
void c_update(int ro,int L,int R){
if (L == R){
vmax[ro] = delta;
vmin[ro] = delta;
laz[ro] = 0;
return ;
}
push_down(ro,L,R);
int M = (L + R) >> 1;
if (ql <= M) c_update(lson(ro),L,M);
else c_update(rson(ro),M+1,R);
push_up(ro);
}
int query(int ro,int L,int R){
if (ql <= L && R <= qr){
return vmax[ro];
}
push_down(ro,L,R);
int M = (L + R) >> 1;
int ans = -INF;
if (ql <= M) ans = max(ans,query(lson(ro),L,M));
if (M < qr) ans = max(ans,query(rson(ro),M+1,R));
return ans;
}
void split(){
dfs(1,0,0);
dfs(1,1);
for (int i = 1;i < n;i ++){
if (dep[e[i].u] < dep[e[i].v])
swap(e[i].u,e[i].v);
val[idx[e[i].u]] = e[i].w;
}
build(1,1,n);
}
void Negate(int u,int v){
int p = top[u], q = top[v];
int ans = INF;
while(p!=q){
if (dep[p] < dep[q]){
swap(p,q);
swap(u,v);
}
ql = idx[p];
qr = idx[u];
n_update(1,1,n);
u = father[p];
p = top[u];
}
if (u == v)
return;
if (dep[u] > dep[v])
swap(u,v);
ql = idx[son[u]];
qr = idx[v];
n_update(1,1,n);
}
int get_max(int u,int v){
int p = top[u], q = top[v];
int ans = -INF;
while(p!=q){
if (dep[p] < dep[q]){
swap(p,q);
swap(u,v);
}
ql = idx[p];
qr = idx[u];
ans = max(ans,query(1,1,n));
u = father[p];
p = top[u];
}
if (u == v)
return ans;
if (dep[u] > dep[v])
swap(u,v);
ql = idx[son[u]];
qr = idx[v];
ans = max(ans,query(1,1,n));
return ans;
}
void solve(){
char s[20];
while(1){
scanf("%s",s);
if (s[0] == 'D')
break;
else if (s[0] == 'Q'){
int u,v;
scanf("%d%d",&u,&v);
printf("%d\n",get_max(u,v));
}else if (s[0] == 'C'){
int i,v;
scanf("%d%d",&i,&v);
ql = idx[e[i].u];
delta = v;
c_update(1,1,n);
}else {
int u,v;
scanf("%d%d",&u,&v);
Negate(u,v);
}
}
}
int main(){
int t;
//freopen("1.txt","r",stdin);
scanf("%d",&t);
while(t--){
input();
split();
solve();
}
return 0;
}
poj 3237 Tree 树链剖分
最新推荐文章于 2019-07-17 22:15:00 发布