为了体现我29买的typora的价值,本文用typora编辑
题目链接
思路
就是裸的(但不是神的)DSU on tree
但是主教练给了个思考方向:bfs序???很合理,深深感觉思路被局限了。
蒟蒻只会看题解,尽管这是一道简单题(我不会dsu)
代码
#include<bits/stdc++.h> using namespace std; const int maxn=1e5+10; #define pii pair<int,int> vector<pii>q[maxn];//存储问题 struct Node{ string name; int fa,num; }node[maxn]; struct Edge{ int v,nxt; }edge[maxn]; int head[maxn],edgetot; void add(int u,int v){ // cout<<"add "<<u<<' '<<v<<endl; edge[++edgetot]=(Edge){v,head[u]}; head[u]=edgetot; } int dep[maxn],sz[maxn],son[maxn],ans[maxn]; void dfs1(int u,int fa){ dep[u]=dep[fa]+1; if(!head[u])sz[u]=1; for(int i=head[u];i;i=edge[i].nxt){ int v=edge[i].v; dfs1(v,u); if(sz[son[u]]<sz[v])son[u]=v; sz[u]+=sz[v]; } } set<string>name[maxn*2]; int vis[maxn]; void del(int x){ name[dep[x]].clear(); for(int i=head[x];i;i=edge[i].nxt)del(edge[i].v); } void add(int x){ // cout<<"add u fa"<<" "<<edge[head[x]].v<<endl; name[dep[x]].insert(node[x].name); for(int i=head[x];i;i=edge[i].nxt)add(edge[i].v); // cout<<"added u fa"<<" "<<x<<endl; } void dfs2(int u,int fa){//dsu 探究某深度的个数 vis[u]=1; for(int i=head[u];i;i=edge[i].nxt){//轻 int v=edge[i].v; if(v==son[u])continue; dfs2(v,u); del(v); } if(son[u])dfs2(son[u],u);//重 for(int i=head[u];i;i=edge[i].nxt){ if(edge[i].v!=son[u])add(edge[i].v);//重儿子之前操作了妹清空 } name[dep[u]].insert(node[u].name);//加进去后统计答案 for(auto i:q[u])ans[i.second]=name[i.first].size(); //[dsu]意义在于不用清空son[u] } int main(){ // ios::sync_with_stdio(0),cin.tie(0); int n,m,k,v,r; cin>>n; string s; for(int i=1;i<=n;++i){ cin>>s>>r; node[i]=(Node){s,r,i}; add(r,i); } for(int i=1;i<=n;++i)if(!dep[i])dfs1(i,0); cin>>m; for(int i=1;i<=m;++i){ cin>>v>>k; q[v].push_back({dep[v]+k,i}); } for(int i=1;i<=n;++i) if(!vis[i])dfs2(i,0),del(i); for(int i=1;i<=m;++i)cout<<ans[i]<<"\n" ; return 0; }
代码有点丑,不过好在代码不长