Naked problem, but because of the right edge, so you have to put the edge on the edge of the child nodes, and then the chain update/query can not update/query its LCA.
#include <cstdio> #include <cmath> #include <algorithm>using namespace std; #define N 100001#define BN 320#define INF 2147483647int 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]];p ushdown (NUM[PL]); A[pl]=y;calc (NUM[PL]);} void Cov (const int &X,CONST int &y,const int &v) {pushdown (num[x]);p Ushdown (Num[y]), if (Num[x]==num[y]) {WOR K_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]);p Ushdown (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]);p Ushdown (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;}
Tree chain split, block, recent public ancestor, Block tree, bzoj1984 month, Mao Jingxiu