codeforces 600E. Lomsat gelral
阿新 • • 發佈:2018-11-22
題意:給一棵樹,每個節點有一個編號,求每顆子樹最多編號的和。
線段樹合併模板題
#include<cstdio> #include<algorithm> #include<vector> using namespace std; typedef long long ll; const int maxn=1e5+10; vector<int>G[maxn]; int mx[maxn*20],rt[maxn*20],ls[maxn*20],rs[maxn*20],V[maxn],n,cnt=0; ll ans[maxn],sum[maxn*20]; void pushup(int o) { mx[o]=max(mx[ls[o]],mx[rs[o]]); if(mx[ls[o]]==mx[rs[o]])sum[o]=sum[ls[o]]+sum[rs[o]]; else { if(mx[ls[o]]>mx[rs[o]])sum[o]=sum[ls[o]]; else sum[o]=sum[rs[o]]; } } int merge(int a,int b,int l,int r) { if(!a||!b)return a|b; if(l==r) { sum[a]=l; mx[a]+=mx[b]; return a; } int m=(l+r)/2; if(ls[a]||ls[b])ls[a]=merge(ls[a],ls[b],l,m); if(rs[a]||rs[b])rs[a]=merge(rs[a],rs[b],m+1,r); pushup(a); return a; } void up(int &o,int l,int r,int k) { if(!o)o=++cnt; if(l==r) { mx[o]++; sum[o]=l; return; } int m=(l+r)/2; if(k<=m)up(ls[o],l,m,k); else up(rs[o],m+1,r,k); pushup(o); } void dfs(int u,int fa) { for(int i=0;i<G[u].size();i++) { if(G[u][i]==fa)continue; dfs(G[u][i],u); merge(rt[u],rt[G[u][i]],1,n); } up(rt[u],1,n,V[u]); ans[u]=sum[rt[u]]; } int main() { int u,v; scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d",&V[i]),rt[i]=++cnt; for(int i=1;i<n;i++) { scanf("%d%d",&u,&v); G[u].push_back(v); G[v].push_back(u); } dfs(1,0); for(int i=1;i<n;i++)printf("%I64d ",ans[i]); printf("%I64d\n",ans[n]); }
看了一些這題關於啟發式合併的題解,也需要重鏈剖分,按照網上大神的程式碼仿寫了一遍,假裝自己學懂了啟發式合併.....
#include<cstdio> #include<algorithm> #include<vector> using namespace std; typedef long long ll; const int maxn=1e5+10; vector<int>G[maxn]; int son[maxn],size[maxn],a[maxn],f[maxn],vis[maxn],cnt[maxn],mx=0; ll sum=0,ans[maxn]; void dfs(int u,int fa) { f[u]=fa; size[u]=1; for(int i=0;i<G[u].size();i++) { int v=G[u][i]; if(v==fa)continue; dfs(v,u); size[u]+=size[v]; if(size[v]>size[son[u]])son[u]=v; } } void cal(int u,int v) { cnt[a[u]]+=v; if(cnt[a[u]]==mx)sum+=a[u]; else if(cnt[a[u]]>mx)sum=a[u],mx=cnt[a[u]]; for(int i=0;i<G[u].size();i++) if(G[u][i]!=f[u]&&!vis[G[u][i]]) cal(G[u][i],v); } void dfs2(int u) { for(int i=0;i<G[u].size();i++) if(G[u][i]!=f[u]&&G[u][i]!=son[u])dfs2(G[u][i]); if(son[u])dfs2(son[u]),vis[son[u]]=1; cal(u,1); ans[u]=sum; if(son[u])vis[son[u]]=0; if(son[f[u]]!=u)cal(u,-1),sum=0,mx=0; } int main() { int n,u,v; scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d",&a[i]); for(int i=1;i<n;i++) { scanf("%d%d",&u,&v); G[u].push_back(v); G[v].push_back(u); } dfs(1,0); dfs2(1); for(int i=1;i<n;i++)printf("%I64d ",ans[i]); printf("%I64d\n",ans[n]); }