树链剖分模板题,代码量挺大的。因为弱,所以常数大的飞起,直接T了。实在没办法卡了,无奈放弃卡常,不要脸的粘贴了一份题解。先上自己写的代码:
typedef long long LL; using namespace std; LL read(){ LL x=0,f=1;char c=getchar(); while(c<'0' || c>'9'){ if(c=='-') f=-1; c=getchar(); } while(c>='0' && c<='9') x=x*10+c-'0',c=getchar(); return x*f; } struct w{ LL ll,rr,mx,sm; }tr[4*maxn]; LL head[maxn],nxt[2*maxn],pnt[2*maxn],cnt=0; LL v[maxn],size[maxn],deep[maxn],fa[maxn],son[maxn]; LL top[maxn],tid[maxn],rnk[maxn]; void add(LL x,LL y){ ++cnt;nxt[cnt]=head[x],head[x]=cnt; pnt[cnt]=y; } void build(LL now,LL pre,LL dep){ size[now]=1; deep[now]=dep; fa[now]=pre; for(LL i=head[now];i!=-1;i=nxt[i]){ LL to=pnt[i]; if(to==pre) continue; build(to,now,dep+1); size[now]+=deep[now]; if(son[now]==-1 || size[to]>size[son[now]]) son[now]=to; } } void dfs(LL now,LL t){ ++cnt; top[now]=t; tid[now]=cnt; rnk[cnt]=now; if(son[now]==-1) return ; dfs(son[now],t); for(LL i=head[now];i!=-1;i=nxt[i]){ LL to=pnt[i]; if(to!=son[now] && to!=fa[now]) dfs(to,to); } } LL askmx(LL now,LL l,LL r){ LL ans=-2e9; if(tr[now].ll==l && tr[now].rr==r) return tr[now].mx; LL mid=(tr[now].ll+tr[now].rr)/2; if(r<=mid) ans=max(ans,askmx(now*2,l,r)); else if(l>mid) ans=max(ans,askmx(now*2+1,l,r)); else ans=max(ans,max(askmx(now*2+1,mid+1,r),askmx(now*2,l,mid))); return ans; } LL fndmx(LL x,LL y){ LL ans=-2e9; LL fx=top[x],fy=top[y]; while(fx^fy){ if(deep[fx]<deep[fy]) swap(fx,fy),swap(x,y); ans=max(ans,askmx(1,tid[fx],tid[x])); x=fa[fx],fx=top[x]; } if(deep[x]>deep[y]) ans=max(ans,askmx(1,tid[y],tid[x])); else ans=max(ans,askmx(1,tid[x],tid[y])); return ans; } LL asksm(LL now,LL l,LL r){ LL ans=0; if(tr[now].ll==l && tr[now].rr==r) return tr[now].sm; LL mid=(tr[now].ll+tr[now].rr)/2; if(r<=mid) ans+=asksm(now*2,l,r); else if(l>mid) ans+=asksm(now*2+1,l,r); else ans+=asksm(now*2,l,mid)+asksm(now*2+1,mid+1,r); return ans; } LL fndsm(LL x,LL y){ LL ans=0; LL fx=top[x],fy=top[y]; while(fx^fy){ if(deep[fx]<deep[fy]) swap(fx,fy),swap(x,y); ans+=asksm(1,tid[fx],tid[x]); x=fa[fx],fx=top[x]; } if(deep[x]>deep[y]) ans+=asksm(1,tid[y],tid[x]); else ans+=asksm(1,tid[x],tid[y]); return ans; } void buildtree(LL now,LL l,LL r){ if(l==r){tr[now]=(w){l,r,v[rnk[l]],v[rnk[l]]};return ;} LL mid=(l+r)/2; buildtree(now*2,l,mid),buildtree(now*2+1,mid+1,r); tr[now]=(w){l,r,max(tr[now*2].mx,tr[now*2+1].mx),tr[now*2].sm+tr[now*2+1].sm}; } void update(LL now,LL x,LL jia){ if(tr[now].ll==tr[now].rr){tr[now].mx+=jia,tr[now].sm+=jia;return ;} LL mid=(tr[now].ll+tr[now].rr)/2; if(x<=mid) update(now*2,x,jia); else update(now*2+1,x,jia); tr[now].mx=max(tr[now*2].mx,tr[now*2+1].mx); tr[now].sm=tr[now*2].sm+tr[now*2+1].sm; } int main(){ freopen("1036.in","r",stdin); freopen("1036.out","w",stdout); memset(head,-1,sizeof(head)),memset(son,-1,sizeof(son)); LL n=read(); for(LL i=1;i<=n-1;i++){ LL x=read(),y=read(); add(x,y),add(y,x); } cnt=0; for(LL i=1;i<=n;i++) v[i]=read(); size[1]=1,build(1,-1,1); dfs(1,1); buildtree(1,1,n); LL q=read(); while(q--){ string s;cin>>s;LL len=s.length(); LL x=read(),y=read(); if(s[len-1]=='E') update(1,tid[x],y-v[x]),v[x]=y; if(s[len-1]=='X'){ LL ans=fndmx(x,y); printf("%lld\n",ans); } if(s[len-1]=='M'){ LL ans=fndsm(x,y); printf("%lld\n",ans); } } return 0; }
大佬写的博客安利一下,很清楚http://blog.csdn.net/jiangshibiao/article/details/24669751
最后提交的代码就是这个上面的标程(超级不要脸的好不好!)