[CF55D] Beautiful numbers - 數位dp
阿新 • • 發佈:2020-11-22
大致題意
給一顆\(n\)個節點的樹,現在有\(m\)次操作,每次選擇兩個節點\(u\),\(v\),對\(u\)到\(v\)的路徑上的每個節點都發放一袋\(z\)型別的物品
求所有操作完成後,每個點存放最多的是哪種物品
\(n,m≤10^5,z≤10^9\)
分析
線段樹合併模板題
差分+離散化一下
每次操作時將\(u\)和\(v\)的權值線段樹中的\(z\)位置\(+1\),\(lca(u,v)\)和\(fa_{lca(u,v)}\)中的\(z\)位置\(-1\),所有操作完成後再\(dfs\)一遍合併子樹
複雜度\((n+m)log(n+m)\)
\(code\)
#include<bits/stdc++.h> using namespace std; const int MAXN = 100010; int n,m; int f[MAXN][21],dep[MAXN]; inline int read(){ int X=0; bool flag=1; char ch=getchar(); while(ch<'0'||ch>'9') {if(ch=='-') flag=0; ch=getchar();} while(ch>='0'&&ch<='9') {X=(X<<1)+(X<<3)+ch-'0'; ch=getchar();} if(flag) return X; return ~(X-1); } struct st{ int lson,rson,val,pos; }tree[MAXN*100]; int tot,root[MAXN]; struct e{ int v,next; }edge[MAXN<<1]; int head[MAXN<<1],cnt; void add(int u,int v){ edge[++cnt].v = v; edge[cnt].next = head[u]; head[u] = cnt; } struct Lca{ void dfs(int u,int fa){ dep[u] = dep[fa]+1; f[u][0] = fa; for(int i=1;(1<<i)<=dep[u];i++){ f[u][i] = f[f[u][i-1]][i-1]; } for(int i=head[u];i;i=edge[i].next){ int v = edge[i].v; if(v==fa) continue; dfs(v,u); } } int lca(int u,int v){ if(dep[u]>dep[v]) swap(u,v); for(int i=20;i>=0;i--){ if(dep[u]<=dep[v]-(1<<i)) v = f[v][i]; } if(u==v) return u; for(int i=20;i>=0;i--){ if(f[u][i]!=f[v][i]){ u = f[u][i]; v = f[v][i]; } } return f[u][0]; } }LCA; void pushup(int node){ tree[node].val = max(tree[tree[node].lson].val,tree[tree[node].rson].val); tree[node].pos = tree[tree[node].lson].val>=tree[tree[node].rson].val?tree[tree[node].lson].pos:tree[tree[node].rson].pos; } void insert(int &node,int l,int r,int pos,int val){ if(!node) node = ++tot; if(l==r){ tree[node].val += val; tree[node].pos = l; return; } int mid = (l+r)>>1; if(pos<=mid) insert(tree[node].lson,l,mid,pos,val); else if(pos>mid)insert(tree[node].rson,mid+1,r,pos,val); pushup(node); } int merge(int a,int b,int l,int r){ if(!b) return a; if(!a) return b; if(l==r){ tree[a].val+=tree[b].val; tree[a].pos = tree[a].val?l:0; return a; } int mid = (l+r)>>1; tree[a].lson = merge(tree[a].lson,tree[b].lson,l,mid); tree[a].rson = merge(tree[a].rson,tree[b].rson,mid+1,r); pushup(a); return a; } int len; int a[MAXN],b[MAXN],c[MAXN]; int value[MAXN]; int ans[MAXN]; int getid(int x){ return lower_bound(value+1,value+1+len,c[x]) - value; } void dfs2(int u,int fa){ for(int i=head[u];i;i=edge[i].next){ int v = edge[i].v; if(v==fa) continue; dfs2(v,u); merge(root[u],root[v],1,len); } ans[u] = tree[root[u]].pos; } int main(){ n = read(),m = read(); for(int i=1;i<n;i++){ int u = read(),v = read(); add(u,v),add(v,u); } LCA.dfs(1,0); for(int i=1;i<=n;i++) root[i] = ++tot; for(int i=1;i<=m;i++){ a[i] =read(),b[i] = read(),c[i] = read(); value[i] = c[i]; } sort(value+1,value+1+m); len = unique(value+1,value+1+m)-(value+1); for(int i=1;i<=m;i++){ int x = a[i],y = b[i],z = getid(i); int fa = LCA.lca(x,y); int Fa = f[fa][0]; insert(root[x],1,len,z,1); insert(root[y],1,len,z,1); insert(root[fa],1,len,z,-1); if(Fa) insert(root[Fa],1,len,z,-1); } dfs2(1,0); for(int i=1;i<=n;i++){ printf("%d\n",value[ans[i]]); } }