D, LCA is very obvious. It is important to note that, because it is a division, it can be up to 64 times apart from x>2, and can be returned 0 when it is greater than 64. Also notice that there may be many sides with a value of 1, you can use path compression to compress the edges to 1, similar to the path compression of the set.
Previously only compressed to LCA, has been tle, can be directly compressed to their root node.
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include < queue> #include <cmath> #define LL long longusing namespace Std;const int Max=200050;int head[max],tot;struct edge{int u,v,next; LL W;} EDGE[MAX*2]; LL W[max]; int Pre[max],depth[max],edno[max],par[max][20];bool vis[max];queue<int>que;void addedge (int u,int V,LL W) {Edge [Tot].u=u; Edge[tot].v=v; Edge[tot].w=w; Edge[tot].next=head[u]; head[u]=tot++;} int n,m;void BFS (int u) {que.push (U); Depth[u]=1; edno[u]=0; while (!que.empty ()) {U=que.front (); Vis[u]=true; Que.pop (); for (int e=head[u];e!=-1;e=edge[e].next) {int v=edge[e].v; if (Vis[v]) continue; depth[v]=depth[u]+1; Par[v][0]=u; if (w[edno[u]]==1) {pre[v]=pre[u]; EDNO[V]=EDGE[E].W; } else{Pre[v]=u; Edno[v]=edge[e]. W; } que.push (v); }}}void init () {int i,j; For (J=1, (1<<j) <=n;j++) for (i=1;i<=n;i++) if (par[i][j-1]!=-1) Par[i][j]=par[pa R[I][J-1]][J-1];} int LCA (int a,int b)//recent public ancestor {int i,j; if (Depth[a]<depth[b]) swap (A, b); for (i=0; (1<<i) <=depth[a];i++); i--; Make the depth of a, b two point the same for (j=i;j>=0;j--) if (depth[a]-(1<<J) >=depth[b]) a=par[a][j]; if (a==b) return A; Multiplication method, each time to the upward depth of the 2^j, find the nearest common ancestor of the child node for (j=i;j>=0;j--) {if (Par[a][j]!=-1&&par[a][j]!=par[b][j]) {a= PAR[A][J]; B=PAR[B][J]; }} return par[a][0];} LL anum[70]; LL bnum[70]; LL query (int a,int b,ll y) {int ret= (int) (log (double) y)/log (2.0)); int Lca=lca (A, B);///cout<<lca<< "" <<ret<<endl; int ac=0,bc=0; while (A!=-1&&depth[a]>depth[lca]) {////cout<<a<< "" <<w[edno[a]]<<endl; IF (w[edno[a]]>1) {y/=w[edno[a]]; if (y==0) return 0; } int tp=pre[a]; while (pre[tp]!=-1&&w[edno[tp]]==1) {TP=PRE[TP]; } int rt=tp; Tp=a; while (PRE[TP]!=RT) {int TMP=PRE[TP]; Pre[tp]=rt; tp=tmp; } A=rt; } LL ty=y; while (B!=-1&&depth[b]>depth[lca]) {//cout<<b<< "" <<edno[b]<<endl; if (w[edno[b]]>1) {ty/=w[edno[b]]; BNUM[BC++]=W[EDNO[B]]; if (ty==0) return 0; } int tp=pre[b]; while (pre[tp]!=-1&&w[edno[tp]]==1) {TP=PRE[TP]; } int rt=tp; Tp=b; while (PRE[TP]!=RT) {int TMP=PRE[TP]; Pre[tp]=rt; tp=tmp; } B=rt; }///cout<<ac<< "" <<bc<<endl;///cout<<bnum[bc-1]<<endl;///for (int i=0;i<ac ; i++) Y/=anum[i]; for (int i=bc-1;i>=0;i--) y/=bnum[i]; return y;} int main () {int u,v,op,a,b,p,c; LL y; while (scanf ("%d%d", &n,&m)!=eof) {memset (pre,-1,sizeof (pre)); memset (head,-1,sizeof (head)); memset (depth,0,sizeof (depth)); memset (vis,false,sizeof (VIS)); Memset (W,0,sizeof (w)); memset (par,-1,sizeof (PAR)); memset (edno,0,sizeof (Edno)); tot=0; for (int i=1;i<n;i++) {cin>>u>>v>>w[i]; Addedge (U,v,i); Addedge (V,u,i); } BFS (1); cout<<pre[2]<< "" <<edno[2]<<endl; Init (); for (int i=1;i<=m;i++) {scanf ("%d", &op); if (op==1) {cin>>a>>b>>y; Cout<<query (a,b,y) <<endl; } else{cin>>p>>y; W[p]=y; }}} return 0;}
CF #329 D