这道题其实还是比较好想的,同样是边权问题。我们需要维护最大值,最小值,和。最坑的地方就是路径上的所有数变相反数,其实这个就是把区间和*-1,区间最大*-1,区间最小*-1,最后pushdown的时候将取反标记^1,接下来一系列都是常规操作。而这里还要记住,单点修改时也要下传lazy标记。而我在跳链的时候写错了调了很久,样例非常之水。
代码,又臭又长,bzoj上都还AC不了
#include<bits/stdc++.h> using namespace std; const int maxn=3e6+7; struct node{ int l,r,sum,mx,lazy1,mi; }tree[maxn*6]; struct node1{ int nxt,from,to,val; }edge[maxn*4]; int head[maxn],cnt; int x,y,v,n,m; char opt[666]; void add(int x,int y,int v){ edge[++cnt].nxt=head[x]; edge[cnt].from=x; edge[cnt].to=y; edge[cnt].val=v; head[x]=cnt; } int ljb[maxn],dep[maxn],son[maxn],fa[maxn],size[maxn],top[maxn],w[maxn],rev[maxn],id[maxn],Time; void dfs1(int x,int f){ dep[x]=dep[f]+1; fa[x]=f; size[x]=1; int maxson=-1; for(int i=head[x];i;i=edge[i].nxt){ int go=edge[i].to; if(go==fa[x]) continue; w[go]=edge[i].val; dfs1(go,x); size[x]+=size[go]; if(size[go]>maxson){ maxson=size[go]; son[x]=go; } } } void dfs2(int x,int topf){ top[x]=topf; id[x]=++Time; rev[id[x]]=w[x]; if(!son[x]) return; dfs2(son[x],topf); for(int i=head[x];i;i=edge[i].nxt){ int go=edge[i].to; if(go==fa[x]||go==son[x]) continue; dfs2(go,go); } } void pushdown(int now){ if(tree[now].lazy1){ tree[now<<1].sum*=-1; tree[now<<1|1].sum*=-1; swap(tree[now<<1].mx,tree[now<<1].mi); tree[now<<1].mx*=-1; tree[now<<1].mi*=-1; swap(tree[now<<1|1].mx,tree[now<<1|1].mi); tree[now<<1|1].mx*=-1; tree[now<<1|1].mi*=-1; tree[now<<1].lazy1^=1; tree[now<<1|1].lazy1^=1; tree[now].lazy1=0; } } void pushup(int now){ tree[now].sum=tree[now<<1].sum+tree[now<<1|1].sum; tree[now].mi=min(tree[now<<1].mi,tree[now<<1|1].mi); tree[now].mx=max(tree[now<<1].mx,tree[now<<1|1].mx); } void build(int now,int l,int r){ tree[now].l=l,tree[now].r=r; if(l==r){ tree[now].mi=tree[now].mx=tree[now].sum=rev[l]; return; } int mid=(l+r)>>1; build(now<<1,l,mid); build(now<<1|1,mid+1,r); pushup(now); } void update1(int now,int x,int v){ if(tree[now].l==tree[now].r){ tree[now].mi=tree[now].mx=tree[now].sum=v; return; } pushdown(now); int mid=(tree[now].l+tree[now].r)>>1; if(x<=mid) update1(now<<1,x,v); else update1(now<<1|1,x,v); pushup(now); } void update2(int now,int l,int r){ if(tree[now].l>=l&&tree[now].r<=r){ tree[now].sum*=-1; tree[now].lazy1^=1; swap(tree[now].mi,tree[now].mx); tree[now].mi*=-1; tree[now].mx*=-1; return; } pushdown(now); int mid=(tree[now].l+tree[now].r)>>1; if(l<=mid) update2(now<<1,l,r); if(r>mid) update2(now<<1|1,l,r); pushup(now); } void linkup(int x,int y){ while(top[x]!=top[y]){ if(dep[top[x]]<dep[top[y]]) swap(x,y); update2(1,id[top[x]],id[x]); x=fa[top[x]]; } if(dep[x]<dep[y]) swap(x,y); update2(1,id[y]+1,id[x]); } int query1(int now,int l,int r){ if(tree[now].l>=l&&tree[now].r<=r) return tree[now].sum; pushdown(now); int val=0; int mid=(tree[now].l+tree[now].r)>>1; if(l<=mid) val+=query1(now<<1,l,r); if(r>mid) val+=query1(now<<1|1,l,r); return val; } int query2(int now,int l,int r){ if(tree[now].l>=l&&tree[now].r<=r) return tree[now].mx; pushdown(now); int mid=(tree[now].l+tree[now].r)>>1; int val=-0x3f3f3f3f; if(l<=mid) val=max(val,query2(now<<1,l,r)); if(r>mid) val=max(val,query2(now<<1|1,l,r)); return val; } int query3(int now,int l,int r){ if(tree[now].l>=l&&tree[now].r<=r) return tree[now].mi; pushdown(now); int mid=(tree[now].l+tree[now].r)>>1; int val=0x3f3f3f3f; if(l<=mid) val=min(val,query3(now<<1,l,r)); if(r>mid) val=min(val,query3(now<<1|1,l,r)); return val; } int link1(int x,int y){ int ans=0; if(x==y) return 0; while(top[x]!=top[y]){ if(dep[top[x]]<dep[top[y]]) swap(x,y); ans+=query1(1,id[top[x]],id[x]); x=fa[top[x]]; } if(dep[x]<dep[y]) swap(x,y); ans+=query1(1,id[y]+1,id[x]); return ans; } int link2(int x,int y){ int ans=-0x3f3f3f3f; if(x==y) return 0; while(top[x]!=top[y]){ if(dep[top[x]]<dep[top[y]]) swap(x,y); ans=max(ans,query2(1,id[top[x]],id[x])); x=fa[top[x]]; } if(dep[x]<dep[y]) swap(x,y); ans=max(ans,query2(1,id[y]+1,id[x])); return ans; } int link3(int x,int y){ int ans=0x3f3f3f3f; if(x==y) return 0; while(top[x]!=top[y]){ if(dep[top[x]]<dep[top[y]]) swap(x,y); ans=min(ans,query3(1,id[top[x]],id[x])); x=fa[top[x]]; } if(dep[x]<dep[y]) swap(x,y); ans=min(ans,query3(1,id[y]+1,id[x])); return ans; } int o,p,q; int main(){ scanf("%d",&n); for(int i=1;i<n;i++){ scanf("%d%d%d",&x,&y,&v); x++;y++; add(x,y,v);add(y,x,v); } dfs1(1,0); dfs2(1,1); build(1,1,n); scanf("%d",&m); for(int i=1;i<=m;i++){ scanf("%s",opt); if(opt[0]=='C'){ scanf("%d%d",&o,&p); int st=edge[o<<1].from; int ed=edge[o<<1].to; int who=dep[st]<dep[ed]?ed:st; update1(1,id[who],p); } if(opt[0]=='N'){ scanf("%d%d",&o,&p); o++;p++; linkup(o,p); } if(opt[0]=='S'){ scanf("%d%d",&o,&p); o++;p++; printf("%d ",link1(o,p)); } if(opt[1]=='A'){ scanf("%d%d",&o,&p); o++;p++; printf("%d ",link2(o,p)); } if(opt[1]=='I'){ scanf("%d%d",&o,&p); o++;p++; printf("%d ",link3(o,p)); } } return 0; }