题目来源:http://poj.org/problem?id=3237
1、取反再取反等于不取反,注意写法要用异或
2、注意更改的是边而不是点,所以下面标记处要特别注意
3、多组数据,线段树标记要初始化
#include <cstdio>
#include <cstring>
#include <algorithm>
#define lch now<<1
#define rch now<<1|1
using namespace std;
const int N=30000,inf=0x3fffffff;
int T,n,m;
int ver[N<<1],e[N<<1],nxt[N<<1],head[N],tot=1;
int pos[N],p[N];
int size[N],son[N],fa[N],dep[N];
int w[N],top[N],id[N<<1],C[N],W[N];
int a,b,val,L,R,cnt;
struct Tree {
int ma,mi; bool neg;
}I[N<<2];
inline void add (int u,int v,int w,int loc) {
ver[++tot]=v;e[tot]=w;p[tot]=loc;
nxt[tot]=head[u];head[u]=tot;
}
//叶子结点千万不能pushup
inline void pushup (int now) {
I[now].ma=max(I[lch].ma,I[rch].ma);
I[now].mi=min(I[lch].mi,I[rch].mi);
}
void pushdown (int now) {
if (!I[now].neg) return;
swap(I[lch].mi,I[lch].ma);I[lch].mi=-I[lch].mi;I[lch].ma=-I[lch].ma;
swap(I[rch].mi,I[rch].ma);I[rch].mi=-I[rch].mi;I[rch].ma=-I[rch].ma;
I[lch].neg^=1;I[rch].neg^=1;//异或
I[now].neg=0;
}
void dfs_1 (int u,int from) {
size[u]=1;son[u]=0;fa[u]=from;
for (int i=head[u];i;i=nxt[i]) {
int v=ver[i];
if (v==fa[u]) continue;
dep[v]=dep[u]+1; fa[v]=u;
pos[p[i]]=v;
dfs_1(v,u);size[u]+=size[v];
if (!son[u]||size[son[u]]<size[v]) son[u]=v;
}
}
void dfs_2 (int u,int st) {
w[u]=++cnt;top[u]=st;id[cnt]=u;
if (son[u]) dfs_2(son[u],st);
for (int i=head[u];i;i=nxt[i]) {
int v=ver[i];
if (v==son[u]||v==fa[u]) continue;
dfs_2(v,v);
}
}
void build (int now,int l,int r) {
if (l==r) {
I[now].ma=I[now].mi=C[id[l]];
if (id[l]==1) I[now].ma=-inf,I[now].mi=inf;//根特判
I[now].neg=0;
return ;
}
int mid=(l+r)>>1;
build(lch,l,mid); build(rch,mid+1,r);
pushup(now);
}
void change (int now,int l,int r,int pos) {
if (l==r&&l==pos) {
I[now].mi=I[now].ma=val;
I[now].neg=0;
return ;
}
int mid=(l+r)>>1;
pushdown(now);
if (pos<=mid) change(lch,l,mid,pos);
if (pos>mid) change(rch,mid+1,r,pos);
pushup(now);
}
void negate (int now,int l,int r) {
if (l>R||r<L||l>r) return ;
if (L<=l&&r<=R) {
I[now].neg^=1;//这里可能要转回去
swap(I[now].ma,I[now].mi);
I[now].ma=-I[now].ma;I[now].mi=-I[now].mi;
return ;
}
int mid=(l+r)>>1;
pushdown(now);
if (L<=mid) negate(lch,l,mid);
if (R>mid) negate(rch,mid+1,r);
pushup(now);
}
int query (int now,int l,int r) {
if (l>R||r<L||l>r) return -inf;
if (L<=l&&r<=R) {
return I[now].ma;
}
int mid=(l+r)>>1;int ans=-inf;
pushdown(now);
if (L<=mid) ans=max(ans,query(lch,l,mid));
if (R>mid) ans=max(ans,query(rch,mid+1,r));
return ans;
}
int Get (int x,int y,bool opt) {
int ans=-inf;
if (!opt) {
while (top[x]!=top[y]) {
if (dep[top[x]]<dep[top[y]])swap(x,y);
L=w[top[x]]; R=w[x];
negate(1,1,cnt);
x=fa[top[x]];
}
if (x==y) return ans;//处理的是边
if (dep[x]<dep[y]) swap(x,y);
L=w[y]+1; R=w[x];//处理的是边
negate(1,1,cnt);
}
else {
while (top[x]!=top[y]) {
if (dep[top[x]]<dep[top[y]])swap(x,y);
L=w[top[x]]; R=w[x];
ans=max(ans,query(1,1,cnt));
x=fa[top[x]];
}
if (x==y) return ans;//处理的是边
if (dep[x]<dep[y]) swap(x,y);
L=w[y]+1; R=w[x];//处理的是边
ans=max(ans,query(1,1,cnt));
}
return ans;
}
int main () {
char str[30];
int u,v,cap;
scanf("%d",&T);
while (T--) {
scanf("%d",&n);
memset(head,0,sizeof(head));
memset(pos,0,sizeof(pos));
memset(p,0,sizeof(p));
memset(size,0,sizeof(size));
memset(son,0,sizeof(son));
memset(fa,0,sizeof(fa));
memset(dep,0,sizeof(dep));
cnt=0;tot=1;
for (int i=1;i<n;i++) {
scanf("%d%d%d",&u,&v,&cap);
add(u,v,cap,i); add(v,u,cap,i);
W[i]=cap;
}
for (int i=0;i<(N<<2);i++) I[i].neg=0;//这里初始化一开始忘了
dfs_1(1,0); dfs_2(1,1);
for (int i=1;i<n;i++) C[pos[i]]=W[i]; //C[1]=-inf;//
//特判根节点
build(1,1,cnt);
while (scanf("%s",str)!=EOF) {
if (str[0]=='D') break;
if (str[0]=='C') {
scanf("%d%d",&a,&val);
change(1,1,cnt,w[pos[a]]);
}
else if (str[0]=='N') {
scanf("%d%d",&a,&b);
Get(a,b,0);
}
else if (str[0]=='Q') {
scanf("%d%d",&a,&b);
printf("%d\n",Get(a,b,1));
}
}
}
return 0;
}