【BzoJ 4719】【Noip2016】【天天爱跑步】【lca】【方程移项】【桶排优化】
来源:互联网 发布:hecras软件 编辑:程序博客网 时间:2024/05/20 03:38
4719: [Noip2016]天天爱跑步
Time Limit: 40 Sec Memory Limit: 512 MBSubmit: 1337 Solved: 451
[Submit][Status][Discuss]
Description
Input
Output
输出1行N 个整数,第个整数表示结点的观察员可以观察到多少人。
Sample Input
2 3
1 2
1 4
4 5
4 6
0 2 5 1 2 3
1 5
1 3
2 6
Sample Output
HINT
Source
HOME Back
想到去年考noip时,当时写了一个暴力bfs就觉得是正解还真是naive呢;
本体由于n和m都会很大,所以如果是每个路径都暴力跑一次保证TLE没的说;
那么若想AC,肯定是经过预处理后直接求值,而且复杂度绝对不会超过 O(n*log(n));
那么我们细看一个观察员若是正好看到某个人跑过的时候需要满足的性质:
【1】deep[S] - deep[i] = t[i]
【2】lon - (deep[E] - deep[i]) = t[i] (S为一个跑步者的起点,E为终点;t[i]为站在点i上的观察员看人的时间)
那么就可以推导出式子
【1】deep[S] = t[i] +deep[i]
【2】lon - deep[E] = t[i] - deep[i]
那么我们不就可以发现一个点上可以看到的人数可以用两个桶表示;
那么怎么合并桶嘞?
我们发现经过一个点时,会有一些S或E使桶中的一些元素值增加,也会有一些LCA(S , E)(即一个路径不会再被经过时)使得一些元素值减少,所以我们可以不用去想合并桶,而是便利点时顺带加减(此处运用的是差分的思想)
那么在此整理总结一下:
本题由于如果是便利每条路径绝对会TLE,所以使我们想到可能是需要集中在一起处理;
由于推出式子:
【1】deep[S] - deep[i] = t[i]
【2】lon - (deep[E] - deep[i]) = t[i]
然后由于我们看到这个等式同测的未知数并不统一,但是可以通过移向使其变得统一,所以得到等式:
【1】deep[S] = t[i] +deep[i](针对S -> LCA 路径上的点)
【2】lon - deep[E] = t[i] - deep[i](针对S -> LCA 路径上的点)
然后发现一个点上的观察员可以看到的跑步者都会有上述特性的其中一个,便想使用两个桶(一个针对S,一个针对E)将其储存起来(于是利用到了查分);那么一个点的答案便是【桶1】[t[i] + deep[i]] +【桶2】[t[i] - deep[i] +3 * 10 ^5](由于是相减可能出现负数,所以需要将等式2左右两边同时加一个3 * 10 ^5以保证其肯定不为负,变为等式:lon - deep[E] + 3 * 10 ^5 = t[i] - deep[i] + 3 * 10 ^5)
注意:
(1)本题还有一个坑点在于对于一个路径的lca来说他同时在S -> LCA 和E -> LCA两条路径上,所以计算时会算重复,此处需要通过控制什么时候增加桶值什么时候减少桶值来解决此类问题
(2)虽然上面说了:答案便是【桶1】[t[i] + deep[i]] +【桶2】[t[i] - deep[i] +3 * 10 ^5]‘;但是因为算法实现时并非合并桶,所以当前的桶并不是你为根的子树的值,需要减去之前其他树上算出的值
代码如下:
#include<vector>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#define M 300001using namespace std;int n , m , w[M] , ans[M];int ind[M] , nex[M * 2] , e[M * 2] ,cnt;int st_up[M] , st_do[M * 2] , dip[M] , st[M][21];vector<int> u_add[M] , u_div[M] , d_add[M] , d_div[M];void add(int a , int b){nex[++cnt] = ind[a];e[ind[a] = cnt] = b;}void Init(int v , int f){dip[v] = dip[f] + 1;st[v][0] = f;for(int i = 1 ; i <= 20 ; ++i)st[v][i] = st[st[v][i - 1]][i - 1];for(int i = ind[v] ; i ; i = nex[i])if(e[i] != f)Init(e[i] , v);}int get_lca(int a , int b){if(dip[a] < dip[b])swap(a , b);int k = dip[a] - dip[b];for(int i = 20 ; i >= 0 ; --i)if((1 << i) <= k){a = st[a][i];k -= (1 << i);}if(a == b)return a;for(int i = 20 ; i >= 0 ; --i)if(st[a][i] != st[b][i]){a = st[a][i];b = st[b][i];}return st[a][0];}void dfs(int v , int f){int x = st_up[dip[v] + w[v]] , y = st_do[w[v] - dip[v] + M];for(int i = ind[v] ; i ; i = nex[i])if(e[i] != f)dfs(e[i] , v);for(int i = 0 ; i < u_add[v].size() ; ++i)st_up[u_add[v][i]]++;for(int i = 0 ; i < d_add[v].size() ; ++i)st_do[d_add[v][i]]++;for(int i = 0 ; i < u_div[v].size() ; ++i)st_up[u_div[v][i]]--;ans[v] = st_up[dip[v] + w[v]] + st_do[w[v] - dip[v] + M] - x - y;for(int i = 0 ; i < d_div[v].size() ; ++i)st_do[d_div[v][i]]--;}int main(){scanf("%d%d",&n,&m);for(int i = 1 ; i < n ; ++i){int a , b;scanf("%d%d",&a,&b);add(a , b);add(b , a);}Init(1 , 0);for(int i = 1 ; i <= n ; ++i)scanf("%d",&w[i]);for(int i = 1 ; i <= m ; ++i){int st , ed;scanf("%d%d",&st,&ed);int lca = get_lca(st , ed);int lon = dip[st] + dip[ed] - dip[lca] * 2;u_add[st].push_back(dip[st]);u_div[lca].push_back(dip[st]);d_add[ed].push_back(lon - dip[ed] + M);d_div[lca].push_back(lon - dip[ed] + M);}dfs(1 , 0);for(int i = 1 ; i <= n ; ++i)printf("%d ",ans[i]);}/*6 32 31 2 1 4 4 5 4 6 0 2 5 1 2 3 1 5 1 3 2 6*/
- 【BzoJ 4719】【Noip2016】【天天爱跑步】【lca】【方程移项】【桶排优化】
- [BZOJ]4719: [Noip2016]天天爱跑步 LCA+奇技淫巧
- 【BZOJ】4719 [Noip2016]天天爱跑步 LCA+树上差分
- 【bzoj 4719】[Noip2016]天天爱跑步
- BZOJ 4719: [Noip2016]天天爱跑步 tarjanlca
- UOJ 261/bzoj 4719(LCA)(NOIP2016)(天天爱跑步)
- NOIP2016天天爱跑步 题解报告【lca+树上统计(桶)】
- UOJ261 NOIP2016 day1 T2 天天爱跑步 (lca + 桶 )
- [NOIP2016]天天爱跑步(lca+乱搞)
- Noip2016 天天爱跑步【LCA】【差分】
- BZOJ4719(NOIP2016)[天天爱跑步]--LCA+DFS
- bzoj 4719: [Noip2016]天天爱跑步 线段树合并
- NOIP2016 天天爱跑步
- [NOIP2016]天天爱跑步
- [NOIP2016]天天爱跑步
- NOIP2016 天天爱跑步
- NOIP2016 天天爱跑步
- 【NOIP2016】天天爱跑步
- 直播预告 | 东南大学周张泉:基于知识图谱的推理技术
- 知识图谱 vs. 对话系统专题讨论
- 感觉灵感被掏空?你需要这 9 篇论文来补一补 | PaperDaily #05
- 多线程(一)
- openstack创建实例失败,bug(1)解决办法
- 【BzoJ 4719】【Noip2016】【天天爱跑步】【lca】【方程移项】【桶排优化】
- 第七周 项目四-队列数组
- 如何做好一个数据分析师?
- 洛谷P1084:疫情控制 (二分答案+倍增+贪心)
- 指针
- 使用字节流复制文件过程中容易导致复制的文件无法使用(如MP3文件比原来大了一千多倍且音乐无法播放)很严重的一个bug
- IFE-TASK11(任务十一:移动Web页面布局实践)
- 菜鸟先飞之JAVA_反射
- OpengGL