CF593D Happy Tree Party
阿新 • • 發佈:2020-08-19
前言
由於之前沒有寫過這類部落格,特地補一篇
題目
講解
如果你做過這道題: 上帝造題的七分鐘2 / 花神遊歷各國(洛谷)
那麼可能對你做這道題有幫助
我們發現,對於詢問,如果除數不等於\(1\),那麼在log級別的次數內,\(y_i\)即可被除為\(0\)
有了這個發現,我們就很容易求得答案
對於一次詢問,暴力找出這條路徑上所有不等於1的邊,一旦統計數超過\(60(log_2(1e18)\approx 60)\)
這時候就會有人問了:“如果暴力爬樹的時候全都是1的邊不就TLE了嗎?”
誒,我們用一個並查集就可以保證時間複雜度了,如果邊為1,我們直接把它在並查集中連到祖先去
這樣在下次就不會經過它了,從而保證時間複雜度
程式碼
int head[MAXN],tot; struct edge { int v,ID,nxt; LL w; }e[MAXN << 1]; void Add_Edge(int x,int y,LL z,int ID) { e[++tot].v = y; e[tot].w = z; e[tot].ID = ID; e[tot].nxt = head[x]; head[x] = tot; } void Add_Double_Edge(int x,int y,LL z,int ID) { Add_Edge(x,y,z,ID); Add_Edge(y,x,z,ID); } int f[MAXN][18],d[MAXN],eID[MAXN],fa[MAXN],bcj[MAXN]; LL w[MAXN]; int findSet(int x) { if(bcj[x] != x) bcj[x] = findSet(bcj[x]); return bcj[x]; } void dfs(int x,int FA) { d[x] = d[FA] + 1; f[x][0] = FA; for(int i = 1;i <= 17;++ i) f[x][i] = f[f[x][i-1]][i-1]; for(int i = head[x]; i ;i = e[i].nxt) if(!d[e[i].v]) eID[e[i].ID] = e[i].v,w[e[i].v] = e[i].w,dfs(e[i].v,x); } int lca(int x,int y) { if(d[x] < d[y]) swap(x,y); for(int i = 17;i >= 0;-- i) if(d[f[x][i]] >= d[y]) x = f[x][i]; if(x == y) return x; for(int i = 17;i >= 0;-- i) if(f[x][i] != f[y][i]) x = f[x][i],y = f[y][i]; return f[x][0]; } LL a[65],b[65]; void Get(int x,int LCA,LL *z,int &cnt) { while(d[findSet(x)] > d[LCA] && cnt < 60) { x = findSet(x); if(w[x] == 1) bcj[x] = findSet(f[x][0]); else z[++cnt] = w[x]; x = f[x][0]; } } int main() { // freopen(".in","r",stdin); // freopen(".out","w",stdout); n = Read(); m = Read(); for(int i = 1;i < n;++ i) { int u = Read(),v = Read(); Add_Double_Edge(u,v,Read(),i); } for(int i = 1;i <= n;++ i) bcj[i] = i; dfs(1,0); while(m--) { int opt = Read(); if(opt == 1) { int u = Read(),v = Read(),cnta = 0,cntb = 0; LL val = Read(); int LCA = lca(u,v); Get(u,LCA,a,cnta); Get(v,LCA,b,cntb); if(cnta + cntb >= 60) Put(0,'\n'); else { for(int i = 1;i <= cnta && val;++ i) val /= a[i]; for(int i = cntb;i >= 1 && val;-- i) val /= b[i]; Put(val,'\n'); } } else { int p = Read(); w[eID[p]] = Read(); } } return 0; }