update 2019.9.29

分解成为\(u->lca\)和\(lca->v\)

得到两个式子,需要统计子树内部的信息。

用差分维护下,差分维护类似于这个前置题

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int _=5e5+7;
  4. int read() {
  5. int x=0,f=1;char s=getchar();
  6. for(;s>'9'||s<'0';s=getchar()) if(s=='-') f=-1;
  7. for(;s>='0'&&s<='9';s=getchar()) x=x*10+s-'0';
  8. return x*f;
  9. }
  10. int n,m,w[_],S[_],T[_],lca[_],tong[_*3],ans[_];
  11. struct node {int v,nxt,q;}e[_<<1];
  12. struct edge {int x,y;edge(int a=0,int b=0) {x=a,y=b;}};
  13. vector<edge> ad[_*4];
  14. int head[_],tot;
  15. void add(int u,int v) {
  16. e[++tot].v=v;
  17. e[tot].nxt=head[u];
  18. head[u]=tot;
  19. }
  20. int son[_],dep[_],fa[_],siz[_],top[_];
  21. void dfs1(int u,int f) {
  22. fa[u]=f;
  23. dep[u]=dep[f]+1;
  24. siz[u]=1;
  25. for(int i=head[u];i;i=e[i].nxt) {
  26. int v=e[i].v;
  27. if(v==f) continue;
  28. dfs1(v,u);
  29. siz[u]+=siz[v];
  30. if(siz[son[u]]<siz[v]) son[u]=v;
  31. }
  32. }
  33. void dfs2(int u,int topf) {
  34. top[u]=topf;
  35. if(!son[u]) return;
  36. dfs2(son[u],topf);
  37. for(int i=head[u];i;i=e[i].nxt) {
  38. int v=e[i].v;
  39. if(!top[v]) dfs2(v,v);
  40. }
  41. }
  42. int LCA(int x,int y) {
  43. while(top[x]!=top[y]) {
  44. if(dep[top[x]]<dep[top[y]]) swap(x,y);
  45. x=fa[top[x]];
  46. } return dep[x]<dep[y]?x:y;
  47. }
  48. void solve1(int u,int fa) {
  49. int A=tong[dep[u]+w[u]];
  50. for(int i=0;i<(int)ad[u].size();++i)
  51. tong[ad[u][i].x]+=ad[u][i].y;
  52. for(int i=head[u];i;i=e[i].nxt)
  53. if(e[i].v!=fa) solve1(e[i].v,u);
  54. int B=tong[dep[u]+w[u]];
  55. ans[u]+=B-A;
  56. }
  57. void solve2(int u,int fa) {
  58. int A=tong[w[u]-dep[u]+2*n];
  59. for(int i=0;i<(int)ad[u].size();++i)
  60. tong[ad[u][i].x]+=ad[u][i].y;
  61. for(int i=head[u];i;i=e[i].nxt)
  62. if(e[i].v!=fa) solve2(e[i].v,u);
  63. int B=tong[w[u]-dep[u]+2*n];
  64. ans[u]+=B-A;
  65. }
  66. int main() {
  67. n=read(),m=read();
  68. for(int i=1;i<n;++i) {
  69. int u=read(),v=read();
  70. add(u,v),add(v,u);
  71. }
  72. for(int i=1;i<=n;++i) w[i]=read();
  73. dfs1(1,0),dfs2(1,1);
  74. for(int i=1;i<=m;++i) S[i]=read(),T[i]=read(),lca[i]=LCA(S[i],T[i]);
  75. for(int i=1;i<=m;++i) {
  76. ad[S[i]].push_back(edge(dep[S[i]],1));
  77. ad[fa[lca[i]]].push_back(edge(dep[S[i]],-1));
  78. }
  79. solve1(1,0);
  80. for(int i=1;i<=n*3;++i) ad[i].clear();
  81. for(int i=1;i<=m;++i) {
  82. ad[lca[i]].push_back(edge(dep[S[i]]-2*dep[lca[i]]+2*n,-1));
  83. ad[T[i]].push_back(edge(dep[S[i]]-2*dep[lca[i]]+2*n,1));
  84. }
  85. solve2(1,0);
  86. for(int i=1;i<=n;++i) printf("%d ",ans[i]);
  87. return 0;
  88. }

lca真心不太会,这里只介绍60分做法,100的太难辣简单了就不介绍了

n<=1000

zz回溯爆搜

S[i]全部相等

这dfs序都不用lca的,2333,差分,然后输出判断一下是否是0(1到i的时间是固定的)

退化成一条链子

一个点i的ans就是i-time[i]和i+tim[i]的起点个数(当然要合法啦)

乱搞就好了,这里写的nlogn的

  1. #include <iostream>
  2. #include <queue>
  3. #include <cstdio>
  4. #include <cstring>
  5. using namespace std;
  6. const int maxn=300000;
  7. const int maxn_25=1000;
  8. struct edge {
  9. int v,nxt;
  10. }e[maxn<<1];
  11. struct node {
  12. int x,id;
  13. bool operator < (const node b) const {
  14. return x>b.x;
  15. }
  16. };
  17. struct node1 {
  18. int x,id;
  19. bool operator < (const node1 b) const {
  20. return x<b.x;
  21. }
  22. };
  23. int head[maxn<<1],tot;
  24. int tim[maxn],n,m,S[maxn],T[maxn],deep[maxn<<1];
  25. int pd_25,ans_25[maxn_25]; //baoli 25 zhuanyong
  26. int tot_a,a_c[maxn<<1],find_a[maxn],ans_c[maxn];//all s == 1 zhuanyong
  27. int vis[maxn<<1],cf[maxn<<1],dsr[maxn<<1];
  28. int ans[maxn];
  29. void add_edge(int u,int v) {
  30. e[++tot].v=v;
  31. e[tot].nxt=head[u];
  32. head[u]=tot;
  33. }
  34. inline int read() {
  35. int x=0,f=1;char s=getchar();
  36. while(s<'0'||s>'9')
  37. {if(s=='-')f=-1;s=getchar();}
  38. while(s>='0'&&s<='9')
  39. {x=(x<<3)+(x<<1)+s-'0',s=getchar();}
  40. return x*f;
  41. }
  42. void dfs_25(int u,int f,int end,int cnt) {
  43. if(u==end) {
  44. if(cnt==tim[u]) ans_25[u]++;
  45. pd_25=1;
  46. return;
  47. }
  48. if(pd_25) return;
  49. if(cnt==tim[u]) ans_25[u]++;
  50. for(int i=head[u];i;i=e[i].nxt) {
  51. int v=e[i].v;
  52. if(v==f) continue;
  53. dfs_25(v,u,end,cnt+1);
  54. if(pd_25) return;
  55. }
  56. if(cnt==tim[u]) ans_25[u]--;
  57. }
  58. void dfs_deep(int u,int f,int cnt) {
  59. deep[u]=cnt;
  60. for(int i=head[u];i;i=e[i].nxt) {
  61. int v=e[i].v;
  62. if(f==v) continue;
  63. dfs_deep(v,u,cnt+1);
  64. }
  65. }
  66. void dfs_xu(int u,int f) {
  67. a_c[++tot_a]=0;
  68. find_a[u]=tot_a;
  69. for(int i=head[u];i;i=e[i].nxt) {
  70. int v=e[i].v;
  71. if(v==f) continue;
  72. dfs_xu(v,u);
  73. }
  74. a_c[++tot_a]=0;
  75. vis[tot_a]=u;
  76. dsr[u]=tot_a;
  77. }
  78. int main() {
  79. n=read(),m=read();
  80. for(int i=1;i<n;++i) {
  81. int x=read(),y=read();
  82. add_edge(x,y);
  83. add_edge(y,x);
  84. }
  85. for(int i=1;i<=n;++i)
  86. tim[i]=read();
  87. for(int i=1;i<=m;++i)
  88. S[i]=read(),T[i]=read();
  89. //baoli_25
  90. if(n<=1000) {
  91. for(int i=1;i<=m;++i) {
  92. pd_25=0;
  93. dfs_25(S[i],0,T[i],0);
  94. }
  95. for(int j=1;j<=n;++j)
  96. printf("%d ",ans_25[j]);
  97. return 0;
  98. }
  99. int wakaka=1;
  100. for(int i=1;i<=m;++i)
  101. if(S[i]!=1) wakaka=0;
  102. if(wakaka)
  103. {
  104. //all S[i]==1 fen==20
  105. dfs_deep(1,0,0);//1 -> i deep
  106. dfs_xu(1,0);
  107. //chafen
  108. for(int i=1;i<=m;++i) {
  109. //1->i
  110. cf[find_a[S[i]]]++;
  111. cf[find_a[T[i]]+1]--;
  112. }
  113. //qiouhe
  114. for(int i=1;i<=tot_a;++i) {
  115. a_c[i]=a_c[i-1]+cf[i];
  116. }
  117. for(int i=1;i<=n;++i) {
  118. if(deep[i]==tim[i])
  119. printf("%d ",a_c[find_a[i]]-a_c[dsr[i]]);
  120. else
  121. printf("0 ");
  122. }
  123. return 0;
  124. }
  125. priority_queue<node> q;
  126. for(int i=1;i<=m;++i)
  127. {
  128. if(S[i] > T[i]) continue;
  129. dsr[S[i]]++;
  130. node x;
  131. x.x=T[i]+1;
  132. x.id=S[i];
  133. q.push(x);
  134. }
  135. for(int i=1;i<=n;++i)
  136. {
  137. while(!q.empty()&&q.top().x==i)
  138. dsr[q.top().id]--,q.pop();
  139. if(i-tim[i]>=1)
  140. ans[i]+=dsr[i-tim[i]];
  141. }
  142. priority_queue< node1 > qq;
  143. memset(dsr,0,sizeof(dsr));
  144. for(int i=1;i<=m;++i)
  145. {
  146. if(S[i] <= T[i]) continue;
  147. dsr[S[i]]++;
  148. node1 x;
  149. x.x=T[i]-1;
  150. x.id=S[i];
  151. qq.push(x);
  152. }
  153. for(int i=n;i>=1;--i)
  154. {
  155. while(!qq.empty()&&qq.top().x==i)
  156. dsr[qq.top().id]--,qq.pop();
  157. // puts("debug");
  158. // for(int j=1;j<=n;++j)
  159. // cout<<dsr[j]<<" ";puts("");
  160. if(i+tim[i]<=n)
  161. ans[i]+=dsr[i+tim[i]];
  162. }
  163. for(int i=1;i<=n;++i)
  164. printf("%d ",ans[i]);
  165. return 0;
  166. }

P1600 天天爱跑步的更多相关文章

  1. [NOIP 2016D2T2/Luogu P1600] 天天爱跑步 (LCA+差分)

    待填坑 Code //Luogu P1600 天天爱跑步 //Apr,4th,2018 //树上差分+LCA #include<iostream> #include<cstdio&g ...

  2. [luogu]P1600 天天爱跑步[LCA]

    [luogu]P1600 [NOIP 2016]天天爱跑步 题目描述 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.«天天爱跑步»是一个养成类游戏,需要玩家每天按时上 ...

  3. 洛谷P1600 天天爱跑步(线段树合并)

    小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.<天天爱跑步>是一个养成类游戏,需要玩家每天按时上线,完成打卡任务. 这个游戏的地图可以看作一一棵包含 nn ...

  4. P1600 天天爱跑步[桶+LCA+树上差分]

    题目描述 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.<天天爱跑步>是一个养成类游戏,需要玩家每天按时上线,完成打卡任务. 这个游戏的地图可以看作一一棵 ...

  5. 洛谷 P1600 天天爱跑步

    https://www.luogu.org/problemnew/show/P1600 (仅做记录) 自己的假方法: 每一次跑从a到b:设l=lca(a,b)对于以下产生贡献: a到l的链上所有的点( ...

  6. 洛谷P1600 天天爱跑步——树上差分

    题目:https://www.luogu.org/problemnew/show/P1600 看博客:https://blog.csdn.net/clove_unique/article/detail ...

  7. Luogu:P1600 天天爱跑步

    来一发清新的80行 树剖 $LCA$ + 树上差分 题解. -----from Judge 本题题意大概是给出一棵 n 个节点的树以及 m 条有向路径, 并且每个点 i 都有一个权值 $w[i]$,如 ...

  8. 洛谷P1600 天天爱跑步

    天天放毒... 首先介绍一个树上差分. 每次进入的时候记录贡献,跟出来的时候的差值就是子树贡献. 然后就可以做了. 发现考虑每个人的贡献有困难. 于是考虑每个观察员的答案. 把路径拆成两条,以lca分 ...

  9. luogu P1600 天天爱跑步

    传送门 1A此题暴祭 (下面记点\(x\)深度为\(de_x\),某个时间点记为\(w_x\)) 首先,每条路径是可以拆成往上和往下两条路径的 对于往上的路径,假设有个人往上跑,\(w_y\)在点\( ...

随机推荐

  1. Tomcat项目部署的三种方法

    第一种方法如下:直接把我们的项目文件夹放到tomcat里面,在这里我自己做的是一个测试项目oa,如图 启动tomcat,打开浏览器,输入localhost/oa  即可打开你的文件,注意 :访问的时候 ...

  2. Python3学习之路~2.1 列表、元组操作

    列表 列表是我们以后最常用的数据类型之一,通过列表可以对数据实现最方便的存储.修改等操作. 定义列表(list) names=['Amy','Bob','Cindy','David'] 通过下标访问列 ...

  3. [git]git版本管理学习记录

    今天看到别人用这玩意记录自己的进度, 我也学习了一下. 1,适当的工具会提升效率 2,关注点还是得放在代码本身上. github/gitignore github提供了各种gitignore文件 有p ...

  4. Mr Cao 的提问

    block调用时,变量的生命周期有哪几种?分别是什么样的? 98.CALayer的多个sublaye的数据结构,以及重绘顺序? 99.网路请求的超时及重试机制应该如何设计? 100.NSDiction ...

  5. redis windows版本下载

    https://github.com/dmajkic/redis/downloads http://windows.php.net/downloads/pecl/snaps/redis/3.1.4rc ...

  6. 谷歌浏览器使用IE内核

    经常使用谷歌浏览器去到处溜达,可是,居然还不知道谷歌浏览的还有很多新鲜的设置,昨天遇到了调试一个脚本没有出现效果,而在IE中就可以显示所谓的效果: 查询了下,看到谷歌浏览器确实对脚本的部分样式要求还是 ...

  7. Python中的is和==的区别,==判断值是否相等,is判断地址是否一致

    Python中的is和==的区别 Python中的对象包含三要素:id.type.value. 其中id用来唯一标示一个对象,type标识对象的类型,value是对象的值. is判断的是a对象是否就是 ...

  8. python json-json.loads()函数中的字符串需要是严格的json串格式,不能包含单引号

    先看下json的dumps()和loads()函数的定义 json.dumps():将一个Python对象编码成JSON字符串.把字典对象转换成json串 json.loads():将JSON格式字符 ...

  9. js 技巧(智能社教程温故)

    1.js 中  NaN === NaN  值为false; 2.parseInt("abc") === NaN;(不是数字) 3.tab 纯js 实现.可以给当前循环的元素添加.i ...

  10. linux服务器---安装swat

    安装swat swat是一个图形化的samba管理软件,可以帮助不熟悉的人去灵活的配置samba服务, 1.安装swat [root@localhost wj]#yum install -y samb ...