在yzc的RP++模板下:
我完成了成熟版的树链剖分
本次更新的主要内容:
1.趋向于把值存在点上
2.引入了dfs序的概念
3.成功的只建一棵线段树,从此和可持久化说再见
#include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<functional> #include<iostream> #include<cmath> #include<cctype> #include<ctime> using namespace std; #define For(i,n) for(int i=1;i<=n;i++) #define Fork(i,k,n) for(int i=k;i<=n;i++) #define Rep(i,n) for(int i=0;i<n;i++) #define ForD(i,n) for(int i=n;i;i--) #define RepD(i,n) for(int i=n;i>=0;i--) #define Forp(x) for(int p=pre[x];p;p=next[p]) #define Lson (x<<1) #define Rson ((x<<1)+1) #define MEM(a) memset(a,0,sizeof(a)); #define MEMI(a) memset(a,127,sizeof(a)); #define MEMi(a) memset(a,128,sizeof(a)); #define INF (2139062143) #define F (100000007) #define MAXN (30000+10) #define MAXM (200000+10) long long mul(long long a,long long b){return (a*b)%F;} long long add(long long a,long long b){return (a+b)%F;} long long sub(long long a,long long b){return (a-b+(a-b)/F*F+F)%F;} typedef long long ll; int n,m; ll sum[MAXN<<3]={0},maxv[MAXN<<3]={0}; void update(int x){sum[x]=sum[Lson]+sum[Rson],maxv[x]=max(maxv[Lson],maxv[Rson]);} void change(int x,int l,int r,int L,int c) { if (l==r) {sum[x]=maxv[x]=c;return;} int m=l+r>>1; if (L<=m) change(Lson,l,m,L,c); else change(Rson,m+1,r,L,c); update(x); } ll qurrysum(int x,int l,int r,int L,int R) { if (L<=l&&r<=R) return sum[x]; int m=l+r>>1; ll ans=0; if (L<=m) ans+=qurrysum(Lson,l,m,L,R); if (m<R) ans+=qurrysum(Rson,m+1,r,L,R); return ans; } ll qurrymax(int x,int l,int r,int L,int R) { if (L<=l&&r<=R) return maxv[x]; int m=l+r>>1; ll ans=-INF; if (L<=m) ans=max(ans,qurrymax(Lson,l,m,L,R)); if (m<R) ans=max(ans,qurrymax(Rson,m+1,r,L,R)); return ans; } int edge[MAXN*2],pre[MAXN]={0},next[MAXN*2]={0},size=0; void addedge(int u,int v) { edge[++size]=v; next[size]=pre[u]; pre[u]=size; } void addedge2(int u,int v){addedge(u,v),addedge(v,u);} int dep[MAXN]={0},siz[MAXN]={0},opt[MAXN]={0},father[MAXN]={0}; void dfs(int x) { siz[x]=1; dep[x]=dep[father[x]]+1; Forp(x) { int &v=edge[p]; if (v^father[x]) { father[v]=x; dfs(v); siz[x]+=siz[v]; if (siz[v]>siz[opt[x]]) opt[x]=v; } } } int top[MAXN],w[MAXN],place[MAXN],tim=0; void dfs2(int x,int chain) { top[x]=chain; place[x]=++tim; change(1,1,n,place[x],w[x]); if (opt[x]) dfs2(opt[x],chain);else return; Forp(x) { int &v=edge[p]; if (v^father[x]&&v^opt[x]) { dfs2(v,v); } } } ll lca_sum(int u,int v) { ll ans=0; while (top[u]^top[v]) { if (dep[top[u]]<dep[top[v]]) swap(u,v); ans+=qurrysum(1,1,n,place[top[u]],place[u]); u=father[top[u]]; } if (dep[u]<dep[v]) swap(u,v); ans+=qurrysum(1,1,n,place[v],place[u]); return ans; } ll lca_max(int u,int v) { ll ans=-INF; while (top[u]^top[v]) { if (dep[top[u]]<dep[top[v]]) swap(u,v); ans=max(ans,qurrymax(1,1,n,place[top[u]],place[u])); u=father[top[u]]; } if (dep[u]<dep[v]) swap(u,v); ans=max(ans,qurrymax(1,1,n,place[v],place[u])); return ans; } char c[10]; int main() { // freopen("bzoj1036.in","r",stdin); scanf("%d",&n); /* For(i,n) { int p,l,r,c; cin>>p>>l>>r; if (p==1) change(1,1,n,l,r); if (p==2) cout<<qurrysum(1,1,n,l,r)<<endl; if (p==3) cout<<qurrymax(1,1,n,l,r)<<endl; }*/ For(i,n-1) { int u,v; scanf("%d%d",&u,&v); addedge2(u,v); } For(i,n) scanf("%d",&w[i]); dfs(1); dfs2(1,1); scanf("%d",&m); For(i,m) { int a,b; scanf("%s%d%d",c,&a,&b); switch(c[1]) { case'H':change(1,1,n,place[a],b);break; case'S':printf("%lld\n",lca_sum(a,b));break; case'M':printf("%lld\n",lca_max(a,b)); } } return 0; }