JS防抖節流函式的實現與使用場景
阿新 • • 發佈:2021-07-15
每個節點上開一個cnti陣列表示i這個數字出現了多少次,那麼節點i上出現最多的數字就是cnt陣列的最大值。
然後每次的操作可以調整為:
在u v上打一個+1的標記,在uv的lca上打一個-1的標記,在lca的父親上打一個-1的標記。
然後打完標記後從葉子開始啟發式的向上合併。
假設當前節點是u。
首先比較u的線段樹sz和u的兒子們的最大線段樹sz,小的往大的上面合併。
然後剩下的線段樹無腦往這個最大的線段樹上合併,那麼最終的線段樹就是u的狀態。
然後題目要求輸出最小的編號。
這裡考慮直接線上段樹上維護。
即id[i]表示節點i所在的區間內的最大值的最小編號。
然後往上pushup的時候應該是可以完全合併的。
另外,求lca可以直接倍增。
注意坑點:當一個點上最大次數為0的時候答案是0,不判斷的話應該會輸出1
#include<bits/stdc++.h> using namespace std; const int maxn=1e5+10; const int M=maxn*80; int tot; int c[M],id[M],lson[M],rson[M],sz[M],T[maxn]; void pushup (int newRoot) { c[newRoot]=max(c[lson[newRoot]],c[rson[newRoot]]); if (c[lson[newRoot]]==c[newRoot]) id[newRoot]=id[lson[newRoot]]; else id[newRoot]=id[rson[newRoot]]; sz[newRoot]=sz[lson[newRoot]]+sz[rson[newRoot]]+1; } int up (int i,int l,int r,int p,int v) { int newRoot=i; if (!newRoot) newRoot=++tot,sz[newRoot]=1; if (l==r) { c[newRoot]+=v; id[newRoot]=l; return newRoot; } int mid=(l+r)>>1; if (p<=mid) lson[newRoot]=up(lson[newRoot],l,mid,p,v); if (p>mid) rson[newRoot]=up(rson[newRoot],mid+1,r,p,v); pushup(newRoot); return newRoot; } int merge (int x,int y,int l,int r) { //合併根為x和y的線段樹,返回新的根 if (!x) return y; if (!y) return x; if (l==r) { c[x]+=c[y]; return x; } if (sz[x]<sz[y]) swap(x,y); int mid=(l+r)>>1; lson[x]=merge(lson[x],lson[y],l,mid); rson[x]=merge(rson[x],rson[y],mid+1,r); pushup(x); return x; } int n; vector<int> g[maxn]; int h[maxn],father[25][maxn]; void dfs (int x) { for (int y:g[x]) { if (y==father[0][x]) continue; father[0][y]=x; h[y]=h[x]+1; dfs(y); } } int lca (int x,int y) { if (h[x]<h[y]) swap(x,y); for (int i=20;i>=0;i--) { if (h[x]-h[y]>>i) x=father[i][x]; } if (x==y) return x; for (int i=20;i>=0;i--) { if (father[i][x]!=father[i][y]) { x=father[i][x]; y=father[i][y]; } } return father[0][x]; } int ans[maxn]; void dfs1 (int x) { for (int y:g[x]) { if (y==father[0][x]) continue; dfs1(y); } int maxson=-1,u=0; for (int y:g[x]) { if (y==father[0][x]) continue; if (sz[T[y]]>maxson) { maxson=sz[T[y]]; u=y; } } if (u) T[x]=merge(T[x],T[u],1,1e5); for (int y:g[x]) { if (y==father[0][x]) continue; if (y==u) continue; T[x]=merge(T[x],T[y],1,1e5); } ans[x]=id[T[x]]; if (c[T[x]]==0) ans[x]=0; } int m; int main () { scanf("%d%d",&n,&m); for (int i=1;i<n;i++) { int x,y; scanf("%d%d",&x,&y); g[x].push_back(y); g[y].push_back(x); } dfs(1); for (int i=1;i<=20;i++) { for (int j=1;j<=n;j++) { father[i][j]=father[i-1][father[i-1][j]]; } } while (m--) { int x,y,z; scanf("%d%d%d",&x,&y,&z); T[x]=up(T[x],1,1e5,z,1); T[y]=up(T[y],1,1e5,z,1); T[lca(x,y)]=up(T[lca(x,y)],1,1e5,z,-1); T[father[0][lca(x,y)]]=up(T[father[0][lca(x,y)]],1,1e5,z,-1); } dfs1(1); for (int i=1;i<=n;i++) printf("%d\n",ans[i]); }