P1600 [NOIP2016 提高组] 天天爱跑步 (树上差分)
对于一条路径,s-t,位于该路径上的观察员能观察到运动员当且仅当以下两种情况成立:(d[ ]表示节点深度)
1.观察员x在s-lca(s,t)上时,满足d[s]=d[x]+w[x]就能观察到,所以我们在这条路径上每个点都放置一个d[s]的物品(差分实现),所有路径处理完后dfs一遍,查询每个节点d[x]+w[x]的物品有多少个就是该种情况的答案。
2.观察员x在lca(s,t)-t上时,同理有d[s]+d[t]-2*d[z]-w[x]=d[t]-d[x],移项的d[s]-2*d[z]=w[x]-d[x],放置d[s]-2*d[z]的物品,查询w[x]-d[x]的物品有多少个,(注意w[x]-d[x]有可能是负数,所以都加上一个n)。
代码中用vector存每个节点的物品,a1,a2是第一种情况的+1和-1;b1,b2是第二种情况的+1和-1;
对于查询子树和,开两个桶实现(全局开桶),满足区间减法,递归回溯回来后-刚遍历时就是子树和,也就是答案。
1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<algorithm>
5 #include<cmath>
6 #include<vector>
7 #include<queue>
8 using namespace std;
9 const int N=300010;
10 int to[N<<1],nxt[N<<1],head[N],tot;
11 int f[N][20],d[N],w[N],v[N];
12 int c1[N<<1],c2[N<<1],ans[N];
13 int n,m,t;
14 queue<int> q;
15 vector<int> a1[N],b1[N],a2[N],b2[N];
16
17 void add(int x,int y){
18 nxt[++tot]=head[x];
19 head[x]=tot;
20 to[tot]=y;
21 }
22
23 void bfs(){
24 t=log(n)/log(2);
25 q.push(1);d[1]=1;
26 while(q.size()){
27 int x=q.front();q.pop();
28 for(int i=head[x];i;i=nxt[i]){
29 int y=to[i];
30 if(d[y]) continue;
31 d[y]=d[x]+1;
32 f[y][0]=x;
33 for(int j=1;j<=t;j++)
34 f[y][j]=f[f[y][j-1]][j-1];
35 q.push(y);
36 }
37 }
38 }
39
40 int lca(int x,int y){
41 if(d[x]>d[y]) swap(x,y);
42 for(int i=t;i>=0;i--)
43 if(d[f[y][i]]>=d[x]) y=f[y][i];
44 if(x==y) return x;
45 for(int i=t;i>=0;i--)
46 if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
47 return f[x][0];
48 }
49
50 void dfs(int x){
51 int val1=c1[d[x]+w[x]],val2=c2[w[x]-d[x]+n];//防止负数,加一个n
52 v[x]=1;
53 for(int i=head[x];i;i=nxt[i]){
54 int y=to[i];
55 if(v[y]) continue;
56 dfs(y);
57 }
58 for(int i=0;i<a1[x].size();i++) c1[a1[x][i]]++;
59 for(int i=0;i<b1[x].size();i++) c1[b1[x][i]]--;
60 for(int i=0;i<a2[x].size();i++) c2[a2[x][i]+n]++;
61 for(int i=0;i<b2[x].size();i++) c2[b2[x][i]+n]--;
62 ans[x]+=c1[d[x]+w[x]]-val1+c2[w[x]-d[x]+n]-val2;//末态-初态,相当于就是统计了子树和
63 }
64
65 int main(){
66 cin>>n>>m;
67 for(int i=1;i<n;i++){
68 int x,y;
69 scanf("%d%d",&x,&y);
70 add(x,y);add(y,x);
71 }
72 for(int i=1;i<=n;i++) scanf("%d",&w[i]);
73 bfs();
74 for(int i=1;i<=m;i++){
75 int x,y;scanf("%d%d",&x,&y);
76 int z=lca(x,y);
77 a1[x].push_back(d[x]);
78 b1[f[z][0]].push_back(d[x]);
79 a2[y].push_back(d[x]-2*d[z]);
80 b2[z].push_back(d[x]-2*d[z]);
81 }
82 dfs(1);
83 for(int i=1;i<n;i++) printf("%d ",ans[i]);
84 printf("%d\n",ans[n]);
85 return 0;
86 }
P1600 [NOIP2016 提高组] 天天爱跑步 (树上差分)的更多相关文章
- [NOIp2016提高组]天天爱跑步
题目大意: 有一棵n个点的树,每个点上有一个摄像头会在第w[i]秒拍照. 有m个人再树上跑,第i个人沿着s[i]到t[i]的路径跑,每秒钟跑一条边. 跑到t[i]的下一秒,人就会消失. 问每个摄像头会 ...
- NOIP2016 Day1 T2 天天爱跑步(树上差分,LCA)
原文链接 原题链接 题目描述 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.<天天爱跑步>是一个养成类游戏,需要玩家每天按时上线,完成打卡任务. 这个游戏 ...
- Luogu P1600[NOIP2016]day1 T2天天爱跑步
号称是noip2016最恶心的题 基本上用了一天来搞明白+给sy讲明白(可能还没讲明白 具体思路是真的不想写了(快吐了 如果要看,参见洛谷P1600 天天爱跑步--题解 虽然这样不好但我真的不想写了 ...
- 洛谷 1600 (NOIp2016) 天天爱跑步——树上差分
题目:https://www.luogu.org/problemnew/show/P1600 看TJ:https://blog.csdn.net/clove_unique/article/detail ...
- 洛谷P1600 天天爱跑步——树上差分
题目:https://www.luogu.org/problemnew/show/P1600 看博客:https://blog.csdn.net/clove_unique/article/detail ...
- 洛谷$P1600$ 天天爱跑步 树上差分
正解:树上差分 解题报告: 传送门$QwQ$! 这题还挺妙的,,,我想了半天才会$kk$ 首先对一条链$S-T$,考虑先将它拆成$S-LCA$和$LCA-T$,分别做.因为总体上来说差不多接下来我就只 ...
- NOIP2016 天天爱跑步 (树上差分+dfs)
题目大意:给你一颗树,树上每个点都有一个观察员,他们仅会在 w[i] 时刻出现,观察正在跑步的玩家 一共有m个玩家,他们分别从节点 s[i] 同时出发,以每秒跑一条边的速度,沿着到 t[i] 的唯一路 ...
- [NOIP2016]天天爱跑步(树上差分+线段树合并)
将每个人跑步的路径拆分成x->lca,lca->y两条路径分别考虑: 对于在点i的观察点,这个人(s->t)能被观察到的充要条件为: 1.直向上的路径:w[i]=dep[s]-dep ...
- NOIP2016 天天爱跑步 - 树上差分
传送门 题目分析: 一年前还是个傻子的时候居然直接放弃了这题. 首先列出两个方程:如果i节点的观察员能够观察到由s->t的那个人,那么: \[dep[s] - dep[i] = w[i], de ...
随机推荐
- Sharding-jdbc 5.1.2案例
简介 sharding-jdbc案例,版本5.1.2 springboot + mybatis-plus + sharding-jdbc 项目地址:sharding-jdbc-example 模块说明 ...
- 常用的函数式接口_Prodicate接口_默认方法or&negate和常用的函数式接口_Predicate接口练习_集合信息筛选
常用的函数式接口_Prodicate接口_默认方法or&negate OR package com.yang.Test.PredicateStudy; import java.util.fun ...
- 中高级Java程序员,挑战20k+,知识点汇总(一),Java修饰符
1 前言 工作久了就会发现,基础知识忘得差不多了.为了复习下基础的知识,同时为以后找工作做准备,这里简单总结一些常见的可能会被问到的问题. 2 自我介绍 自己根据实际情况发挥就行 3 Java SE ...
- Auto.js 特殊定位控件方法 不能在ui线程执行阻塞操作,请使用setTimeout代替
本文所有教程及源码.软件仅为技术研究.不涉及计算机信息系统功能的删除.修改.增加.干扰,更不会影响计算机信息系统的正常运行.不得将代码用于非法用途,如侵立删! Auto.js 特殊定位控件方法 操作环 ...
- Python 爬取汽车之家口碑数据
本文仅供学习交流使用,如侵立删!联系方式见文末 汽车之家口碑数据 2021.8.3 更新 增加用户信息参数.认证车辆信息等 2021.3.24 更新 更新最新数据接口 2020.12.25 更新 添加 ...
- 痞子衡嵌入式:浅析IAR下调试信息输出机制之半主机(Semihosting)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是IAR下调试信息输出机制之半主机(Semihosting). 在嵌入式世界里,输出打印信息是一种非常常用的辅助调试手段,借助打印信息,我 ...
- html + css 实现无需 js 的打字效果
以前要达到类似在电脑上打字的效果,需要 js+html.今天我将介绍一种新方法.本文主要介绍纯 html+css 实现打字效果,有一定的参考价值,大家可以学习一下.提供所有代码,可以直接使用. 一.原 ...
- Python自学教程7:字典类型有什么用
字典是Python中的一个重要操作,如果字典玩得顺,很多其他的数据类型就可以一通百通. Python字典的定义 字典使用一对大括号进行定义,键值对之间使用逗号隔开,键和值使用冒号分隔. 键必须是不可变 ...
- 【unity游戏入门】1 环境安装
作者 罗芭Remoo 2021年9月24日 这一个系列随笔记录如何使用unity引擎从零开始开发游戏,软件版本均使用最新版本 有关unity的背景介绍可以通过unity官网https://unity. ...
- OpenJudge1.5.17
20:球弹跳高度的计算 总时间限制: 1000ms 内存限制: 65536kB 描述 一球从某一高度落下(整数,单位米),每次落地后反跳回原来高度的一半,再落下. 编程计算气球在第10次落地时,共经过 ...