一直以为自己当时是TLE了,但是再看发现居然WA?

然后把数组扩大一倍,就A掉了。QaQ

没什么好说的。一段路径分成两段考虑,上升的一段深度+时间是定值,下降的一段深度-时间是定值,然后打标记统计即可。

发现大概是统计数组因为深度+时间太大炸掉了。

现在想想,当时没有对拍,真是后怕。

#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int read()
{
int ret=0,f=1; char ch=getchar();
while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
while (ch>='0'&&ch<='9'){ret*=10;ret+=ch-'0';ch=getchar();}
return ret*f;
}
int n,m;
int h[600005],to[600002],ne[600002],en=0;
void add(int a,int b)
{
to[en]=b;
ne[en]=h[a];
h[a]=en++;
}
int root=1,dep[600005],fa[600005],son[600005],siz[600005];
vector <int> st[600005];
vector <int> ed[600005];
void dfs1(int k)
{
siz[k]=1;
for (int i=h[k];i>=0;i=ne[i])
if (to[i]!=fa[k]){
fa[to[i]]=k;
dep[to[i]]=dep[k]+1;
dfs1(to[i]);
siz[k]+=siz[to[i]];
if (siz[son[k]]<siz[to[i]]) son[k]=to[i];
}
}
int pos[600005],top[600005],li[600005],cnt=0;
void dfs2(int k,int tp)
{
top[k]=tp;
cnt++; pos[k]=cnt; li[cnt]=k;
if (!son[k]) return ;
if (son[k]) dfs2(son[k],tp);
for (int i=h[k];i>=0;i=ne[i])
if (to[i]!=son[k]&&to[i]!=fa[k]) dfs2(to[i],to[i]);
return ;
}
int w[600005];
vector <int> que[600005];
vector <int> bel[600005];
struct node{int s,t,lca;}q[600005];
int vis[600005],f[600005];
int gf(int k)
{
if (f[k]==k) return k;
else return f[k]=gf(f[k]);
}
void dfs3(int k)
{
f[k]=k;
vis[k]=1;
for (int i=0;i<que[k].size();++i)
if (vis[que[k][i]]) q[bel[k][i]].lca=gf(que[k][i]);
for (int i=h[k];i>=0;i=ne[i])
if (fa[k]!=to[i]){
dfs3(to[i]);
f[to[i]]=k;
}
return ;
}
void lca(){dfs3(1);}
int s[600005],ans[600005];
void add(int a,int b,int fn)
{
if (dep[a]<dep[b]) swap(a,b);
while (top[a]!=top[b])
{
if (dep[top[a]]<dep[top[b]]) swap(a,b);
st[pos[top[a]]].push_back(fn);
ed[pos[a]+1].push_back(fn);
a=fa[top[a]];
}
if (dep[a]<dep[b]) swap(a,b);
st[pos[b]].push_back(fn);
ed[pos[a]+1].push_back(fn);
}
void cal1()
{
for (int i=1;i<=n;++i) w[i]-=dep[i];
for (int i=1;i<=m;++i)
{
int at;
at=dep[q[i].s]-dep[q[i].lca];
if (w[q[i].lca]==at-dep[q[i].lca]) ans[q[i].lca]--;
add(q[i].lca,q[i].t,at-dep[q[i].lca]);
}
for (int i=1;i<=n;++i)
{
for (int j=0;j<st[i].size();++j) s[st[i][j]]++;
for (int j=0;j<ed[i].size();++j) s[ed[i][j]]--;
ans[li[i]]+=s[w[li[i]]];
}
}
void cal2()
{
for (int i=0;i<=n+5;++i) st[i].clear(),ed[i].clear();
memset(s,0,sizeof s);
for (int i=1;i<=n;++i) w[i]+=2*dep[i];
for (int i=1;i<=m;++i)
{
int at;
at=dep[q[i].s]-dep[q[i].lca];
add(q[i].lca,q[i].s,at+dep[q[i].lca]);
}
for (int i=1;i<=n;++i)
{
for (int j=0;j<st[i].size();++j) s[st[i][j]]++;
for (int j=0;j<ed[i].size();++j) s[ed[i][j]]--;
ans[li[i]]+=s[w[li[i]]];
}
}
void out()
{
for (int i=1;i<n;++i)printf("%d ",ans[i]); printf("%d",ans[n]);
}
int main()
{
memset(h,-1,sizeof h);
n=read(); m=read();
for (int i=1;i<n;++i)
{
int a,b;
a=read(); b=read();
add(a,b); add(b,a);
}
for (int i=1;i<=n;++i)
w[i]=read();
for (int i=1;i<=m;++i)
{
int a,b;
a=read(); b=read();
que[a].push_back(b);
que[b].push_back(a);
bel[a].push_back(i);
bel[b].push_back(i);
q[i].s=a;q[i].t=b;
}
dfs1(root);
dfs2(root,root);
lca();
cal1();
cal2();
out();
return 0;
}

  

BZOJ 4719 [Noip2016]天天爱跑步 ——树链剖分的更多相关文章

  1. NOIP2016提高组Day1T2 天天爱跑步 树链剖分 LCA 倍增 差分

    原文链接https://www.cnblogs.com/zhouzhendong/p/9275606.html 题目传送门 - 洛谷P1600 题目传送门 - LOJ#2359 题目传送门 - Vij ...

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

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

  3. bzoj 4719: [Noip2016]天天爱跑步【树上差分+dfs】

    长久以来的心理阴影?但是其实非常简单-- 预处理出deep和每组st的lca,在这里我简单粗暴的拿树剖爆算了 然后考虑对于一组s t lca来说,被这组贡献的观察员x当且仅当: x在s到lca的路径上 ...

  4. [BZOJ 2243] [SDOI 2011] 染色 【树链剖分】

    题目链接:BZOJ - 2243 题目分析 树链剖分...写了200+行...Debug了整整一天+... 静态读代码读了 5 遍 ,没发现错误,自己做小数据也过了. 提交之后全 WA . ————— ...

  5. BZOJ 4568 [Scoi2016]幸运数字(树链剖分 + 异或线性基)

    题目链接  BZOJ 4568 考虑树链剖分+线段树维护每一段区域的异或线性基 对于每个询问,求出该点集的异或线性基.然后求一下这个线性基里面能异或出的最大值即可. #include <bits ...

  6. Bzoj 4196: [Noi2015]软件包管理器 树链剖分

    4196: [Noi2015]软件包管理器 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 721  Solved: 419[Submit][Statu ...

  7. BZOJ 1969: [Ahoi2005]LANE 航线规划( 树链剖分 )

    首先我们要时光倒流, 倒着做, 变成加边操作维护关键边. 先随意搞出一颗树, 树上每条边都是关键边(因为是树, 去掉就不连通了)....然后加边(u, v)时, 路径(u, v)上的所有边都变成非关键 ...

  8. bzoj 4196 [Noi2015]软件包管理器 (树链剖分+线段树)

    4196: [Noi2015]软件包管理器 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 2852  Solved: 1668[Submit][Sta ...

  9. BZOJ - 3631 松鼠的新家 (树链剖分)

    题目链接 树链剖分基础题,路径权值修改+差分 #include<bits/stdc++.h> using namespace std; typedef long long ll; ; in ...

随机推荐

  1. Linux下各文件夹的结构说明及用途介绍(转载)

    linux下各文件夹的结构说明及用途介绍: /bin:二进制可执行命令. /dev:设备特殊文件. /etc:系统管理和配置文件. /etc/rc.d:启动的配 置文件和脚本. /home:用户主目录 ...

  2. Android学习总结(十八) ———— SQLite数据库使用

    一.基本概念 数据库最经典的四个操作 添加.删除.修改.查找,在处理大量数据的时候使用数据库可以帮我们迅速定位当前须要处理的数据,举个例子 好比现在要实现一个搜索功能 用数据库的话只须要其中一个搜索条 ...

  3. Perl 输出内容到 excel

    可以参考:  http://search.cpan.org/~jmcnamara/Spreadsheet-WriteExcel/lib/Spreadsheet/WriteExcel.pm 使用Spre ...

  4. POJ 1655 Balancing Act (树的重心,常规)

    题意:求树的重心,若有多个重心,则输出编号较小者,及其子树中节点最多的数量. 思路: 树的重心:指的是一个点v,在删除点v后,其子树的节点数分别为:u1,u2....,设max(u)为其中的最大值,点 ...

  5. COGS 2211. [BZOJ3653]谈笑风生

    ★★★★   输入文件:laugh.in   输出文件:laugh.out   简单对比时间限制:3 s   内存限制:512 MB [问题描述] 设T 为一棵有根树,我们做如下的定义: • 设a和b ...

  6. 并查集+思维——The Door Problem

    一.问题描述(题目链接) 有n个门和m个开关,每个开关可以控制任意多的门,每个门严格的只有两个开关控制,问能否通过操作某些开关使得所有门都打开.(给出门的初始状态). 二.问题分析 大部分开关问题首先 ...

  7. myna代码

    https://github.com/TalkingData/Myna/tree/master/Dataset https://github.com/TalkingData/Myna

  8. HTML5开发手机应用--viewport的作用--20150216

    在用HTML5开发手机应用或手机网页时,<head>部分总会有如下一段代码,这段代码到底什么意思呢.在网上,大家会得到很多答案.我从网上搜集了部分介绍,整理一下,以留备用. <met ...

  9. javascipt的forEach

    1.Array let arr = [1, 2, 3]; arr.forEach(function (element, index, array) { console.log('数组中每个元素:', ...

  10. linux centeros 通过 innoback 工具备份mysql 5.7 全库并自动压缩zip上传到备份服务器的脚本,附自动清理过期备份

    innoback 安装见连接:https://blog.csdn.net/fanren224/article/details/79693863 脚本解析后续将更新 181024:更新添加定期清理备份的 ...