Link:

BZOJ 4719 传送门

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] 天天爱跑步的更多相关文章

  1. bzoj 4719: [Noip2016]天天爱跑步

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

  2. BZOJ 4719--天天爱跑步(LCA&差分)

    4719: [Noip2016]天天爱跑步 Time Limit: 40 Sec  Memory Limit: 512 MBSubmit: 1464  Solved: 490[Submit][Stat ...

  3. 4719: [Noip2016]天天爱跑步

    Time Limit: 40 Sec Memory Limit: 512 MB Submit: 1986 Solved: 752 [Submit][Status][Discuss] Descripti ...

  4. BZOJ4719[NOIP2016提高组Day1T2] 天天爱跑步

    #261. [NOIP2016]天天爱跑步 描述 提交 自定义测试 小C同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.<天天爱跑步>是一个养成类游戏,需要玩家 ...

  5. UOJ261 【NOIP2016】天天爱跑步

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000作者博客:http://www.cnblogs.com/ljh2000-jump/转 ...

  6. BZOJ4719 [Noip2016]天天爱跑步

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000作者博客:http://www.cnblogs.com/ljh2000-jump/转 ...

  7. noip2016天天爱跑步

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

  8. [NOIP]2016天天爱跑步

    [NOIP]2016天天爱跑步 标签: LCA 树上差分 NOIP Description 小C同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.<天天爱跑步>是 ...

  9. NOIP2016 天天爱跑步 80分暴力

    https://www.luogu.org/problem/show?pid=1600 题目描述 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.«天天爱跑步»是一个养 ...

随机推荐

  1. indexof()函数

    js 判断字符串是否包含某字符串,String对象中查找子字符,indexOf, 成功,返回索引值,失败返回 -1. 转载: http://www.cnblogs.com/fishtreeyu/arc ...

  2. Use of exceptionless, 作全局日志分布式记录处理

    Download latest release of exceptionless on github and deploy on Window server, by default exception ...

  3. 2017ACM暑期多校联合训练 - Team 8 1006 HDU 6138 Fleet of the Eternal Throne (字符串处理 AC自动机)

    题目链接 Problem Description The Eternal Fleet was built many centuries ago before the time of Valkorion ...

  4. Attention is all you need 论文详解(转)

    一.背景 自从Attention机制在提出之后,加入Attention的Seq2Seq模型在各个任务上都有了提升,所以现在的seq2seq模型指的都是结合rnn和attention的模型.传统的基于R ...

  5. flask基础之jijia2模板语言进阶(三)

    前言 前面学习了jijia2模板语言的一些基础知识,接下来继续深挖jijia2语言的用法. 系列文章 flask基础之安装和使用入门(一) flask基础之jijia2模板使用基础(二) 控制语句 和 ...

  6. inet_confirm_addr && confirm_addr_indev

    确认给定参数范围的ip地址是否存在: /* * Confirm that local IP address exists using wildcards: * - net: netns to chec ...

  7. 在ubuntu中安装puppeteer

    https://github.com/GoogleChrome/puppeteer/blob/master/docs/troubleshooting.md 早些时候puppeteer刚出来,在vps上 ...

  8. 7.Python3标准库--文件系统

    ''' Python的标准库中包含大量工具,可以处理文件系统中的文件,构造和解析文件名,还可以检查文件内容. 处理文件的第一步是要确定处理的文件的名字.Python将文件名表示为简单的字符串,另外还提 ...

  9. mysql 创建数据库的时候选择 utf8 bin 和 utf8 ci的区别

    utf8 ci  不区分大小写: utf8 bin 区分大小写:

  10. socket编程——sockaddr_in结构体操作

    sockaddr结构体 sockaddr的缺陷: struct sockaddr 是一个通用地址结构,这是为了统一地址结构的表示方法,统一接口函数,使不同的地址结构可以被bind() , connec ...