Lomsat gelral 树上启发式合并
题目描述
You are given a rooted tree with root in vertex 1 . Each vertex is coloured in some colour.
Let's call colour c dominating in the subtree of vertex v if there are no other colours that appear in the subtree of vertex v more times than colour c . So it's possible that two or more colours will be dominating in the subtree of some vertex.
The subtree of vertex v is the vertex v and all other vertices that contains vertex v in each path to the root.
For each vertex v find the sum of all dominating colours in the subtree of vertex v .
输入格式
The first line contains integer n ( 1<=n<=105 ) — the number of vertices in the tree.
The second line contains n integers ci ( 1<=ci<=n ), ci — the colour of the i -th vertex.
Each of the next n−1 lines contains two integers xj,yj ( 1<=xj,yj<=n ) — the edge of the tree. The first vertex is the root of the tree.
输出格式
Print n integers — the sums of dominating colours for each vertex.
隐藏翻译
题意翻译
- 有一棵 n 个结点的以 1 号结点为根的有根树。
- 每个结点都有一个颜色,颜色是以编号表示的, i 号结点的颜色编号为 ci。
- 如果一种颜色在以 x 为根的子树内出现次数最多,称其在以 x 为根的子树中占主导地位。显然,同一子树中可能有多种颜色占主导地位。
- 你的任务是对于每一个 i∈[1,n],求出以 i 为根的子树中,占主导地位的颜色的编号和。
- n≤105,ci≤n
洛谷崩掉了,cf交的超时,我也不知道怎么办了
好的现在不超时了。dfs_son函数 原本是return int值 改成void就不超时了
原本的单链表存储改成vector了
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10;
int n,color[N],cnt[N];
int sz[N],son[N],idx=0;
int mx;
ll ans[N],sum;
vector<vector<int>>g(N);void dfs_son(int u,int father){sz[u]=1;for(auto i:g[u]){if(i==father)continue;dfs_son(i,u);sz[u]+=sz[i];if(sz[i]>sz[son[u]])son[u]=i;}
}void update(int u,int father,int sign,int pson){int c=color[u];cnt[c]+=sign;if(cnt[c]>mx)mx=cnt[c],sum=c;else if(cnt[c]==mx)sum+=c;for(int i:g[u]){if(i==father||i==pson)continue;update(i,u,sign,pson);}
}void dfs(int u,int father,int op){for(auto i:g[u]){if(i==father||i==son[u])continue;dfs(i,u,0);}if(son[u])dfs(son[u],u,1);update(u,father,1,son[u]);ans[u]=sum;if(!op)update(u,father,-1,0),sum=mx=0;
}int main(){ios::sync_with_stdio(false);cin>>n;for(int i=1;i<=n;++i)cin>>color[i]; int x,y;for(int i=0;i<n-1;++i){cin>>x>>y;g[x].push_back(y);g[y].push_back(x);}dfs_son(1,0);dfs(1,0,1);for(int i=1;i<=n;++i)cout<<ans[i]<<" ";return 0;
}
单链表版
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5*2+10;
int n,color[N],cnt[N];
int h[N],e[N],ne[N],sz[N],son[N],idx=0;
int mx;
ll ans[N],sum;void add(int x,int y){e[idx]=y,ne[idx]=h[x],h[x]=idx++;
}void dfs_son(int u,int father){sz[u]=1;for(int i=h[u];~i;i=ne[i]){int j=e[i];if(j==father)continue;dfs_son(j,u);sz[u]+=sz[j];if(sz[j]>sz[son[u]])son[u]=j;}
}void update(int u,int father,int sign,int pson){int c=color[u];cnt[c]+=sign;if(cnt[c]>mx)mx=cnt[c],sum=c;else if(cnt[c]==mx)sum+=c;for(int i=h[u];~i;i=ne[i]){int j=e[i];if(j==father||j==pson)continue;update(j,u,sign,pson);}
}void dfs(int u,int father,int op){for(int i=h[u];~i;i=ne[i]){int j=e[i];if(j==father||j==son[u])continue;dfs(j,u,0);}if(son[u])dfs(son[u],u,1);update(u,father,1,son[u]);ans[u]=sum;if(!op)update(u,father,-1,0),sum=mx=0;
}int main(){scanf("%d",&n);for(int i=1;i<=n;++i)scanf("%d",&color[i]);memset(h,-1,sizeof(h));int x,y;for(int i=0;i<n-1;++i){scanf("%d%d",&x,&y);add(x,y);add(y,x);}dfs_son(1,-1);dfs(1,-1,1);for(int i=1;i<=n;++i)printf("%lld ",ans[i]);return 0;
}