[BZOJ 4719] 天天爱跑步
Link:
Solution:
感觉求LCA又有了新姿势啊:$Tarjan$离线$O(n+m)$
每次递归返回时将子树和父节点合并,如果询问节点已访问过则LCA就是已合并的最高节点
这题部分分提示非常多啊
首先要将路径拆为$(S,LCA),(LCA,T)$
发现如果$(S,LCA)$能对点$x$产生贡献要满足$w[x]+dep[x]=dep[S]$
而$(LCA,T)$能对点$x$产生贡献要满足$dep[x]-w[x]=dep[T]-len$
这样用$cnt$数组维护等式右边的$dep[S]$和$dep[T]-len$的值有多少个就能快速得出有几条路径满足条件
于是可以在路径起点加入该路径特征值并在路径末尾将其消除即可
注意:
1、$LCA$处可能算了两遍,最后要逐一判断
2、要在刚进入该点时记录当前$cnt[w[x]+dep[x]]$的值否则可能会将其它子树中未走完的路径计算在内
3、此题需要从下往上统计答案,因此路径起点都要设置为深度较大的,否则不好消除不经过该点路径的贡献
Code:
#include <bits/stdc++.h> using namespace std;
#define X first
#define Y second
#define pb push_back
typedef double db;
typedef long long ll;
typedef pair<int,int> P;
const int MAXN=1e6+,ADD=3e5;
int vis[MAXN],f[MAXN],st[MAXN];
int n,q,x,y,w[MAXN],res[MAXN],cnt[MAXN],head[MAXN],dep[MAXN],tot; vector<P> par[MAXN];
vector<int> in[MAXN],out[MAXN];
struct edge{int nxt,to;}e[MAXN<<];
struct Query{int x,y,lca;}qry[MAXN]; void add(int x,int y)
{e[++tot]=(edge){head[x],y};head[x]=tot;}
int find(int x)
{return f[x]==x?x:f[x]=find(f[x]);}
void tarjan(int x,int anc)
{
vis[x]=;f[x]=x;
for(int i=;i<par[x].size();i++)
if(vis[par[x][i].X]) qry[par[x][i].Y].lca=find(par[x][i].X);
for(int i=head[x];i;i=e[i].nxt)
if(e[i].to!=anc)
{
dep[e[i].to]=dep[x]+;
tarjan(e[i].to,x);f[e[i].to]=x;
}
}
void dfs1(int x,int anc)
{
int cur=cnt[w[x]+dep[x]];
for(int i=head[x];i;i=e[i].nxt)
if(e[i].to!=anc) dfs1(e[i].to,x);
cnt[dep[x]]+=st[x];
res[x]+=cnt[w[x]+dep[x]]-cur;
for(int i=;i<out[x].size();i++) cnt[out[x][i]]--;
}
void dfs2(int x,int anc)
{
int cur=cnt[ADD-w[x]+dep[x]];
for(int i=head[x];i;i=e[i].nxt)
if(e[i].to!=anc) dfs2(e[i].to,x);
//都要看成从底向上的路径
for(int i=;i<in[x].size();i++) cnt[in[x][i]]++;
res[x]+=cnt[ADD-w[x]+dep[x]]-cur;
for(int i=;i<out[x].size();i++) cnt[out[x][i]]--;
} int main()
{
scanf("%d%d",&n,&q);
for(int i=;i<n;i++)
scanf("%d%d",&x,&y),add(x,y),add(y,x);
for(int i=;i<=n;i++) scanf("%d",&w[i]);
for(int i=;i<=q;i++)
{
scanf("%d%d",&x,&y);
qry[i].x=x,qry[i].y=y;
par[x].pb(P(y,i));par[y].pb(P(x,i));
}
tarjan(,); for(int i=;i<=q;i++)
out[qry[i].lca].pb(dep[qry[i].x]),st[qry[i].x]++;
dfs1(,);
memset(cnt,,sizeof(cnt));
for(int i=;i<=n;i++) out[i].clear();
for(int i=;i<=q;i++)
{
int len=dep[qry[i].x]+dep[qry[i].y]-*dep[qry[i].lca];
in[qry[i].y].pb(ADD+dep[qry[i].y]-len);
out[qry[i].lca].pb(ADD+dep[qry[i].y]-len);
}
dfs2(,);
for(int i=;i<=q;i++)
if(dep[qry[i].x]-dep[qry[i].lca]==w[qry[i].lca])
res[qry[i].lca]--;
for(int i=;i<=n;i++)
printf("%d ",res[i]);
return ;
}
[BZOJ 4719] 天天爱跑步的更多相关文章
- bzoj 4719: [Noip2016]天天爱跑步
Description 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.?天天爱跑步?是一个养成类游戏,需要 玩家每天按时上线,完成打卡任务.这个游戏的地图可以看作一一 ...
- BZOJ 4719--天天爱跑步(LCA&差分)
4719: [Noip2016]天天爱跑步 Time Limit: 40 Sec Memory Limit: 512 MBSubmit: 1464 Solved: 490[Submit][Stat ...
- 4719: [Noip2016]天天爱跑步
Time Limit: 40 Sec Memory Limit: 512 MB Submit: 1986 Solved: 752 [Submit][Status][Discuss] Descripti ...
- BZOJ4719[NOIP2016提高组Day1T2] 天天爱跑步
#261. [NOIP2016]天天爱跑步 描述 提交 自定义测试 小C同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.<天天爱跑步>是一个养成类游戏,需要玩家 ...
- UOJ261 【NOIP2016】天天爱跑步
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000作者博客:http://www.cnblogs.com/ljh2000-jump/转 ...
- BZOJ4719 [Noip2016]天天爱跑步
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000作者博客:http://www.cnblogs.com/ljh2000-jump/转 ...
- noip2016天天爱跑步
题目描述 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.«天天爱跑步»是一个养成类游戏,需要玩家每天按时上线,完成打卡任务. 这个游戏的地图可以看作一一棵包含 个结点 ...
- [NOIP]2016天天爱跑步
[NOIP]2016天天爱跑步 标签: LCA 树上差分 NOIP Description 小C同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.<天天爱跑步>是 ...
- NOIP2016 天天爱跑步 80分暴力
https://www.luogu.org/problem/show?pid=1600 题目描述 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.«天天爱跑步»是一个养 ...
随机推荐
- $this->success()传值不完整
public function manager_doExport() { $search=$_POST['search']; //前台输入2017-12-1,即,$search['starttime' ...
- CodeForces - 1015D
There are nn houses in a row. They are numbered from 11 to nn in order from left to right. Initially ...
- 【文件上传】jquery之ajaxfileupload异步上传插件
来自:http://www.blogjava.net/sxyx2008/archive/2010/11/02/336826.html 由于项目需求,在处理文件上传时需要使用到文件的异步上传.这里使用J ...
- L - SOS Gym - 101775L 博弈
题目链接:https://cn.vjudge.net/contest/274151#problem/L 题目大意:给你一个1*n的方格,两个人轮流放字母,每一次可以放"S"或者&q ...
- hdfs的datanode工作原理
datanode的作用: (1)提供真实文件数据的存储服务. (2)文件块(block):最基本的存储单位.对于文件内容而言,一个文件的长度大小是size,那么从文件的0偏移开始,按照固定的大小,顺序 ...
- PEB及LDR链
PEB地址的取得在NT内核系统中fs寄存器指向TEB结构,TEB+0x30处指向PEB结构,PEB+0x0c处指向PEB_LDR_DATA结构,PEB_LDR_DATA+0x1c处存放一些指向动态链接 ...
- 64_t5
texlive-mkpattern-svn15878.1.2-33.fc26.2.noarch..> 24-May-2017 15:54 38178 texlive-mkpic-bin-svn3 ...
- MySQL创建相同表和数据命令
创建和表departments结构和数据一样的表departments_t mysql> create table departments_t like departments; Query O ...
- 正排索引(forward index)与倒排索引(inverted index) (转)
一.正排索引(前向索引) 正排索引也称为"前向索引".它是创建倒排索引的基础,具有以下字段. (1)LocalId字段(表中简称"Lid"):表示一个文档的局部 ...
- C语言地址对齐(转)--网络编程之结构体大小的计算
什么是地址对齐? 现代计算机中内存空间都是按照字节(byte)划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定变量的时候经常在特定的内存地址访问,这就需要各类型数 ...