【dfs序+树上差分】ABC309 E

╰半橙微兮° 2024-03-17 17:44 174阅读 0赞

E - Family and Insurance (atcoder.jp)

题意:

b5454fe77bed4f26af4f8ce1f8e58714.png

思路:

对子树进行操作,就可以树上差分

不同的是是对一部分子树操作,因此对于离子树根结点d+1距离的在子树内的结点进行减操作

然后做一次前缀和就行

至于如何判断一个点是否在子树内,只需求出dfs序即可

这里lca判断会多个log,会超时

Code:

  1. #include <bits/stdc++.h>
  2. #define int long long
  3. using namespace std;
  4. const int mxn=1e6+10;
  5. const int mxe=1e6+10;
  6. const int mod=1e9+7;
  7. const int Inf=1e18;
  8. struct ty{
  9. int to,next;
  10. }edge[mxe<<2];
  11. vector<int> V[mxn];
  12. int N,M,tot=0,idx=0;
  13. int x,y;
  14. int Fa[mxn],b[mxn];
  15. int head[mxn],dep[mxn],ans[mxn],F[mxn][33];
  16. int In[mxn],sz[mxn];
  17. void add(int u,int v){
  18. edge[tot].to=v;
  19. edge[tot].next=head[u];
  20. head[u]=tot++;
  21. }
  22. void G_init(){
  23. tot=0;
  24. for(int i=0;i<=N;i++){
  25. head[i]=-1;
  26. }
  27. }
  28. void dfs(int u,int fa){
  29. In[u]=++idx;
  30. sz[u]=1;
  31. dep[u]=dep[fa]+1;
  32. for(int i=head[u];~i;i=edge[i].next){
  33. if(edge[i].to==fa) continue;
  34. dfs(edge[i].to,u);
  35. sz[u]+=sz[edge[i].to];
  36. }
  37. }
  38. void dfs2(int u,int fa){
  39. ans[u]=ans[fa]+b[u];
  40. for(int i=head[u];~i;i=edge[i].next){
  41. if(edge[i].to==fa) continue;
  42. dfs2(edge[i].to,u);
  43. }
  44. }
  45. bool check(int u,int v){
  46. return In[v]>=In[u]&&In[v]<=In[u]+sz[u]-1;
  47. }
  48. void solve(){
  49. cin>>N>>M;
  50. G_init();
  51. for(int i=2;i<=N;i++){
  52. cin>>Fa[i];
  53. add(i,Fa[i]);
  54. add(Fa[i],i);
  55. }
  56. dfs(1,0);
  57. int mx=-1;
  58. for(int i=1;i<=N;i++) mx=max(mx,dep[i]);
  59. for(int i=1;i<=N;i++) V[dep[i]].push_back(i);
  60. for(int i=1;i<=M;i++){
  61. cin>>x>>y;
  62. b[x]++;
  63. if(dep[x]+y+1<=mx){
  64. for(auto it:V[dep[x]+y+1]){
  65. if(check(x,it)) b[it]--;
  66. }
  67. }
  68. }
  69. ans[1]=b[1];
  70. dfs2(1,0);
  71. int cnt=0;
  72. for(int i=1;i<=N;i++){
  73. if(ans[i]!=0) cnt++;
  74. }
  75. cout<<cnt<<'\n';
  76. }
  77. signed main(){
  78. ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
  79. int __=1;//cin>>__;
  80. while(__--)solve();return 0;
  81. }

发表评论

表情:
评论列表 (有 0 条评论,174人围观)

还没有评论,来说两句吧...

相关阅读