【树链剖分】【分块】【最近公共祖先】【块状树】bzoj1984 月下“毛景树”
裸题,但是因为权在边上,所以要先把边权放到这条边的子节点上,然后进行链更新/查询的时候不能更新/查询其lca。
#include<cstdio> #include<cmath> #include<algorithm> using namespace std; #define N 100001 #define BN 320 #define INF 2147483647 int fa[N],dep[N],siz[N],son[N],Num[N],tot,top[N],a[N],bw[N],n,A[N],B[N],bs[N]; int en,first[N],next[N<<1],v[N<<1],sz,NOT; void AddEdge(const int &U,const int &V) { v[++en]=V; next[en]=first[U]; first[U]=en; } void dfs(int U,int Fa,int d) { fa[U]=Fa; dep[U]=d; siz[U]=1; for(int i=first[U];i;i=next[i]) if(v[i]!=fa[U]) { dfs(v[i],U,d+1); siz[U]+=siz[v[i]]; if(siz[v[i]]>siz[son[U]]) son[U]=v[i]; } } void dfs2(int U) { if(son[U]) { top[son[U]]=top[U]; Num[son[U]]=++tot; dfs2(son[U]); } for(int i=first[U];i;i=next[i]) if(v[i]!=fa[U]&&v[i]!=son[U]) { top[v[i]]=v[i]; Num[v[i]]=++tot; dfs2(v[i]); } } int SIZ[N],TOP[N]; void dfs3(int U) { for(int i=first[U];i;i=next[i]) if(v[i]!=fa[U]) { if(SIZ[TOP[U]]<sz) { TOP[v[i]]=TOP[U]; ++SIZ[TOP[U]]; } dfs3(v[i]); } } int lca(int U,int V) { while(U!=V) { if(TOP[U]!=TOP[V]) { if(dep[TOP[U]]<dep[TOP[V]]) swap(U,V); U=fa[TOP[U]]; } else { if(dep[U]<dep[V]) swap(U,V); U=fa[U]; } } return U; } int sum=1,num[N],l[BN],r[BN],maxv[BN],cov[BN],add[BN]; void makeblock() { for(;sum*sz<n;++sum) { l[sum]=r[sum-1]+1; r[sum]=sum*sz; maxv[sum]=-INF; cov[sum]=INF; for(int i=l[sum];i<=r[sum];++i) { num[i]=sum; maxv[sum]=max(maxv[sum],a[i]); } } l[sum]=r[sum-1]+1; r[sum]=n; maxv[sum]=-INF; cov[sum]=INF; for(int i=l[sum];i<=r[sum];++i) { num[i]=sum; maxv[sum]=max(maxv[sum],a[i]); } } void work_cov(const int &x,const int &y,const int &v) { for(int i=x;i<=y;++i) a[i]=v; } void work_add(const int &x,const int &y,const int &v) { for(int i=x;i<=y;++i) a[i]+=v; } void pushdown(const int &bl) { if(cov[bl]!=INF) { work_cov(l[bl],r[bl],cov[bl]); cov[bl]=INF; } if(add[bl]) { work_add(l[bl],r[bl],add[bl]); add[bl]=0; } } void calc(const int &bl) { maxv[bl]=-INF; for(int i=l[bl];i<=r[bl];++i) maxv[bl]=max(maxv[bl],a[i]); } void Update0(const int &x,const int &y) { int pl=Num[bs[x]]; pushdown(num[pl]); a[pl]=y; calc(num[pl]); } void Cov(const int &x,const int &y,const int &v) { pushdown(num[x]); pushdown(num[y]); if(num[x]==num[y]) { work_cov(x,y,v); calc(num[x]); } else { work_cov(x,r[num[x]],v); calc(num[x]); work_cov(l[num[y]],y,v); calc(num[y]); for(int i=num[x]+1;i<num[y];++i) { add[i]=0; cov[i]=maxv[i]=v; } } } void Add(const int &x,const int &y,const int &v) { pushdown(num[x]); pushdown(num[y]); if(num[x]==num[y]) { work_add(x,y,v); calc(num[x]); } else { work_add(x,r[num[x]],v); calc(num[x]); work_add(l[num[y]],y,v); calc(num[y]); for(int i=num[x]+1;i<num[y];++i) { add[i]+=v; maxv[i]+=v; } } } int Query(const int &x,const int &y) { int res=-INF; pushdown(num[x]); pushdown(num[y]); if(num[x]==num[y]) for(int i=x;i<=y;++i) res=max(res,a[i]); else { for(int i=x;i<=r[num[x]];++i) res=max(res,a[i]); for(int i=l[num[y]];i<=y;++i) res=max(res,a[i]); for(int i=num[x]+1;i<num[y];++i) res=max(res,maxv[i]); } return res; } void Change_cov(const int &L,const int &R,const int &W) { if(L==R&&Num[NOT]==L) return; if(Num[NOT]==L) Cov(L+1,R,W); else if(Num[NOT]==R) Cov(L,R-1,W); else if(Num[NOT]>L&&Num[NOT]<R) { Cov(L,Num[NOT]-1,W); Cov(Num[NOT]+1,R,W); } else Cov(L,R,W); } void Update_cov(int U,int V,const int &W) { int f1=top[U],f2=top[V]; while(f1!=f2) { if(dep[f1]<dep[f2]) { swap(U,V); swap(f1,f2); } Change_cov(Num[f1],Num[U],W); U=fa[f1]; f1=top[U]; } if(dep[U]>dep[V]) swap(U,V); Change_cov(Num[U],Num[V],W); } void Change_add(const int &L,const int &R,const int &W) { if(L==R&&Num[NOT]==L) return; if(Num[NOT]==L) Add(L+1,R,W); else if(Num[NOT]==R) Add(L,R-1,W); else if(Num[NOT]>L&&Num[NOT]<R) { Add(L,Num[NOT]-1,W); Add(Num[NOT]+1,R,W); } else Add(L,R,W); } void Update_add(int U,int V,const int &W) { int f1=top[U],f2=top[V]; while(f1!=f2) { if(dep[f1]<dep[f2]) { swap(U,V); swap(f1,f2); } Change_add(Num[f1],Num[U],W); U=fa[f1]; f1=top[U]; } if(dep[U]>dep[V]) swap(U,V); Change_add(Num[U],Num[V],W); } int Talk(const int &L,const int &R) { if(L==R&&Num[NOT]==L) return (-INF); if(Num[NOT]==L) return Query(L+1,R); if(Num[NOT]==R) return Query(L,R-1); if(Num[NOT]>L&&Num[NOT]<R) return max(Query(L,Num[NOT]-1),Query(Num[NOT]+1,R)); return Query(L,R); } int Query_max(int U,int V) { int f1=top[U],f2=top[V],res=-INF; while(f1!=f2) { if(dep[f1]<dep[f2]) { swap(U,V); swap(f1,f2); } res=max(res,Talk(Num[f1],Num[U])); U=fa[f1]; f1=top[U]; } if(dep[U]>dep[V]) swap(U,V); return max(res,Talk(Num[U],Num[V])); } //int cnt,LL[N],RR[N]; //void dfs4(int U) //{ // LL[U]=++cnt; // for(int i=first[U];i;i=next[i]) // if(v[i]!=fa[U]) // dfs4(v[i]); // RR[U]=cnt; //} //int Init(const int &x,const int &y) //{ // if(y>=LL[x]&&y<=RR[x]) return x; // if(x>=LL[y]&&x<=RR[y]) return y; // return lca(x,y); //} int main() { // freopen("bzoj1984.in","r",stdin); scanf("%d",&n); for(int i=1;i<n;++i) { scanf("%d%d%d",&A[i],&B[i],&bw[i]); AddEdge(A[i],B[i]); AddEdge(B[i],A[i]); } top[1]=1; Num[1]=++tot; dfs(1,0,1); dfs2(1); sz=sqrt(n); if(!sz) sz=1; for(int i=1;i<=n;i++) { SIZ[i]=1; TOP[i]=i; } dfs3(1); for(int i=1;i<n;++i) { if(fa[A[i]]==B[i]) bs[i]=A[i]; else bs[i]=B[i]; a[Num[bs[i]]]=bw[i]; } a[Num[1]]=-INF; makeblock(); // dfs4(1); char op[7]; int x,y,z; while(1) { scanf("%s",op); if(op[0]=='S') break; scanf("%d%d",&x,&y); if(op[0]=='C'&&op[1]=='h') Update0(x,y); else if(op[0]=='C'&&op[1]=='o') { NOT=lca(x,y); scanf("%d",&z); Update_cov(x,y,z); } else if(op[0]=='A') { NOT=lca(x,y); scanf("%d",&z); Update_add(x,y,z); } else { NOT=lca(x,y); printf("%d\n",Query_max(x,y)); } } return 0; }
——The Solution By AutSky_JadeK From UESTC
转载请注明出处:http://www.cnblogs.com/autsky-jadek/