poj 3237
题意:给一颗树,边上有权有三种操作
Q u,v u->v路径上权的最大值
C u,v 输入时的第u条边权值修改为v
N u,v u->v路径上边的权值*-1
按照轻重边剖分,取反加个标记就好,记录最大值最小值,取反的时候反过来,再*-1,完成取反操作
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define lc rt<<1 #define rc rt<<1|1 using namespace std; const int maxn=1e4+5; const int INF=1e9; struct Node{int l,r,mx,mi;bool mark;}tr[maxn*4]; struct edge{int to,nxt,v;}e[maxn*3]; int fa[maxn],dep[maxn],son[maxn],siz[maxn],top[maxn]; int p[maxn],cnt,node,val[maxn],fp[maxn],head[maxn]; void addedge(int u,int v,int w){ cnt++;e[cnt].to=v;e[cnt].nxt=head[u]; e[cnt].v=w;head[u]=cnt; } void dfs1(int u){ siz[u]=1;son[u]=0; for(int i=head[u];i;i=e[i].nxt){ int v=e[i].to; if(v==fa[u])continue; fa[v]=u;dep[v]=dep[u]+1;val[v]=e[i].v; dfs1(v); siz[u]+=siz[v]; if(siz[v]>siz[son[u]])son[u]=v; } } void dfs2(int u,int sp){ p[u]=++node;top[u]=sp;fp[node]=u; if(son[u])dfs2(son[u],top[u]); for(int i=head[u];i;i=e[i].nxt){ int v=e[i].to; if(v!=fa[u]&&v!=son[u])dfs2(v,v); } } inline void pushup(int rt){ tr[rt].mx=max(tr[lc].mx,tr[rc].mx); tr[rt].mi=min(tr[lc].mi,tr[rc].mi); } inline void pushdown(int rt){ if(tr[rt].mark){ swap(tr[lc].mi,tr[lc].mx);tr[lc].mi*=-1; swap(tr[rc].mi,tr[rc].mx);tr[rc].mi*=-1; tr[lc].mx*=-1;tr[rc].mx*=-1; tr[lc].mark^=1;tr[rc].mark^=1; tr[rt].mark^=1; } } void build(int rt,int l,int r){ tr[rt].l=l;tr[rt].r=r;tr[rt].mark=false; if(l==r){ tr[rt].mi=tr[rt].mx=val[fp[l]]; } else{ int m=(l+r)>>1; build(lc,l,m);build(rc,m+1,r); pushup(rt); } } void update(int rt,int pp,int v){ int l=tr[rt].l,r=tr[rt].r; if(l==r)tr[rt].mx=tr[rt].mi=v; else{ pushdown(rt); int m=(l+r)>>1; if(pp<=m)update(lc,pp,v); else update(rc,pp,v); pushup(rt); } } void anti(int rt,int a,int b){ int l=tr[rt].l,r=tr[rt].r; if(l==a&&b==r){ tr[rt].mark^=1;swap(tr[rt].mx,tr[rt].mi); tr[rt].mx*=-1;tr[rt].mi*=-1; } else{ pushdown(rt); int m=(l+r)>>1; if(b<=m) anti(lc,a,b); else if(m<a)anti(rc,a,b); else anti(lc,a,m),anti(rc,m+1,b); pushup(rt); } } int query(int rt,int a,int b){ int l=tr[rt].l,r=tr[rt].r; if(l==a&&b==r)return tr[rt].mx; else{ pushdown(rt); int m=(l+r)>>1; if(b<=m)return query(lc,a,b); else if(m<a)return query(rc,a,b); else return max(query(lc,a,m),query(rc,m+1,b)); } } void change(int u,int v){ while(top[u]!=top[v]){ if(dep[top[u]]<dep[top[v]])swap(u,v); anti(1,p[top[u]],p[u]); u=fa[top[u]]; } if(u==v)return ; if(dep[u]>dep[v])swap(u,v); anti(1,p[son[u]],p[v]); } int ask(int u,int v){ int ans=-INF; while(top[u]!=top[v]){ if(dep[top[u]]<dep[top[v]])swap(u,v); ans=max(ans,query(1,p[top[u]],p[u])); u=fa[top[u]]; } if(u==v)return ans; if(dep[u]>dep[v])swap(u,v); return max(ans,query(1,p[son[u]],p[v])); } int ee[maxn][2],u,v,w; int main(){ int t,n;scanf("%d",&t); while(t--){ scanf("%d",&n); cnt=node=0;memset(head,0,sizeof(head)); for(int i=1;i<n;i++){ scanf("%d%d%d",&ee[i][0],&ee[i][1],&w); addedge(ee[i][0],ee[i][1],w); addedge(ee[i][1],ee[i][0],w); } dfs1(1);dfs2(1,1); build(1,1,n); char op[10]; for(int i=1;i<n;i++)if(dep[ee[i][0]]>dep[ee[i][1]])swap(ee[i][0],ee[i][1]); while(true){ scanf("%s",op); if(op[0]=='D')break; scanf("%d%d",&u,&v); if(op[0]=='C'){ u=ee[u][1]; update(1,p[u],v); } else if(op[0]=='Q')printf("%d\n",ask(u,v)); else change(u,v); } } return 0; }