天天放毒...

首先介绍一个树上差分。

每次进入的时候记录贡献,跟出来的时候的差值就是子树贡献。

然后就可以做了。

发现考虑每个人的贡献有困难。

于是考虑每个观察员的答案。

把路径拆成两条,以lca分开。x -> z -> y,完全分成A,B两部分。

那么A:d[x] = w[z] + d[z];B:len - d[y] + N = w[z] - d[z] + N;

这里+ N是为了防止负数。

然后发现右边只跟z有关,这里的z可以是路径上任一点。

那么对于每个人,把需要树上差分统计的左边数值用vector记录。

然后跑一遍统计即可。

注意:如果lca能观测到这条路径,那么--,因为测了A,B两次。

看代码。

 #include <cstdio>
#include <vector> const int N = ; inline void read(int &x) {
x = ;
char c = getchar();
while(c < '' || c > '') {
c = getchar();
}
while(c >= '' && c <= '') {
x = (x << ) + (x << ) + c - ;
c = getchar();
}
return;
} struct Edge {
int v, nex;
}edge[N << ]; int top; int n, m, e[N], w[N], binA[N << ], binB[N << ], cancel[N], d[N], fa[N][], lm, ans[N];
std::vector<int> vA[N], vB[N], vA_[N], vB_[N]; inline void add(int x, int y) {
edge[++top].v = y;
edge[top].nex = e[x];
e[x] = top;
return;
} void DFS1(int x, int f) {
fa[x][] = f;
d[x] = d[f] + ;
for(int i = e[x]; i; i = edge[i].nex) {
int y = edge[i].v;
if(y != f) {
DFS1(y, x);
}
}
return;
} inline void getlca() {
DFS1(, );
while(( << lm) < n) {
lm++;
}
for(int i = ; i <= lm; i++) {
for(int x = ; x <= n; x++) {
fa[x][i] = fa[fa[x][i - ]][i - ];
}
}
return;
} inline int lca(int x, int y) {
int t = lm;
while(d[x] > d[y]) {
std::swap(x, y);
}
while(t > - && d[y] > d[x]) {
if(d[fa[y][t]] >= d[x]) {
y = fa[y][t];
}
t--;
}
if(x == y) {
return x;
}
t = lm;
while(t > - && fa[x][] != fa[y][]) {
if(fa[x][t] != fa[y][t]) {
x = fa[x][t];
y = fa[y][t];
}
t--;
}
return fa[x][];
} void DFS(int x) {
int A = binA[w[x] + d[x]];
int B = binB[w[x] - d[x] + N];
for(int i = e[x]; i; i = edge[i].nex) {
int y = edge[i].v;
if(y != fa[x][]) {
DFS(y);
}
}
for(int i = ; i < vA[x].size(); i++) {
binA[vA[x][i]]++;
}
for(int i = ; i < vB[x].size(); i++) {
binB[vB[x][i]]++;
}
ans[x] += binA[w[x] + d[x]] - A;
ans[x] += binB[w[x] - d[x] + N] - B;
for(int i = ; i < vA_[x].size(); i++) {
binA[vA_[x][i]]--;
}
for(int i = ; i < vB_[x].size(); i++) {
binB[vB_[x][i]]--;
}
return;
} int main() {
read(n);
read(m);
int x, y, z;
for(int i = ; i < n; i++) {
read(x);
read(y);
add(x, y);
add(y, x);
}
for(int i = ; i <= n; i++) {
read(w[i]);
}
getlca();
for(int i = ; i <= m; i++) {
read(x);
read(y);
z = lca(x, y);
vA[x].push_back(d[x]); //d[x] = w[z] + d[z];
vA_[z].push_back(d[x]); //
int len = d[x] + d[y] - * d[z];
vB[y].push_back(len - d[y] + N); //len - d[y] + N = w[z] - d[z] + N;
vB_[z].push_back(len - d[y] + N);
if(d[x] == w[z] + d[z]) {
cancel[z]++;
}
} DFS(); for(int i = ; i <= n; i++) {
printf("%d ", ans[i] - cancel[i]);
}
/*puts("");
for(int i = 1; i < N * 2; i++) {
if(binB[i]) {
printf("binB[%d] = %d\n", i, binB[i]);
}
if(binA[i]) {
printf("binA[%d] = %d\n", i, binA[i]);
}
}
printf("over");*/ return ;
}

AC代码

zbtrs大佬用主席树A了,还说显然是主席树,太强了%%%

洛谷P1600 天天爱跑步的更多相关文章

  1. 洛谷P1600 天天爱跑步(线段树合并)

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

  2. 洛谷 P1600 天天爱跑步

    https://www.luogu.org/problemnew/show/P1600 (仅做记录) 自己的假方法: 每一次跑从a到b:设l=lca(a,b)对于以下产生贡献: a到l的链上所有的点( ...

  3. 洛谷P1600 天天爱跑步——树上差分

    题目:https://www.luogu.org/problemnew/show/P1600 看博客:https://blog.csdn.net/clove_unique/article/detail ...

  4. 洛谷P1600 天天爱跑步(差分 LCA 桶)

    题意 题目链接 Sol 一步一步的来考虑 \(25 \%\):直接\(O(nm)\)的暴力 链的情况:维护两个差分数组,分别表示从左向右和从右向左的贡献, \(S_i = 1\):统计每个点的子树内有 ...

  5. 洛谷 P1600 天天爱跑步(LCA+乱搞)

    传送门 我们把每一条路径拆成$u->lca$和$lca->v$的路径 先考虑$u->lca$,如果这条路径会对路径上的某一个点产生贡献,那么满足$dep[u]-dep[x]=w[x] ...

  6. 洛谷P1600 天天爱跑步——题解

    题目传送 首先要考虑入手点.先考虑一个一个玩家处理,显然不加优化的话,时间复杂度是O(n)的.发现对于玩家路径上的点都有一个观察员,一个都不能忽视,看起来是很难优化了.在做题时,发现一个思路很难想,就 ...

  7. 洛谷$P1600$ 天天爱跑步 树上差分

    正解:树上差分 解题报告: 传送门$QwQ$! 这题还挺妙的,,,我想了半天才会$kk$ 首先对一条链$S-T$,考虑先将它拆成$S-LCA$和$LCA-T$,分别做.因为总体上来说差不多接下来我就只 ...

  8. [NOIP 2016D2T2/Luogu P1600] 天天爱跑步 (LCA+差分)

    待填坑 Code //Luogu P1600 天天爱跑步 //Apr,4th,2018 //树上差分+LCA #include<iostream> #include<cstdio&g ...

  9. AC日记——天天爱跑步 洛谷 P1600

    天天爱跑步 思路: 树上差分+分层动态线段树: (伏地膜,跪烂xxy) 代码: #include <bits/stdc++.h> using namespace std; #define ...

随机推荐

  1. item 11: 比起private undefined function优先使用deleted function

    本文翻译自modern effective C++,由于水平有限,故无法保证翻译完全正确,欢迎指出错误.谢谢! 博客已经迁移到这里啦 如果你为其他开发者提供代码,并且你想阻止他们调用一个特定的函数,你 ...

  2. Nginx SSL+tomcat集群,request.getScheme() 取到https正确的协议

    最近在做一个项目, 架构上使用了 Nginx +tomcat 集群, 且nginx下配置了SSL,tomcat no SSL,项目使用https协议 但是,明明是https url请求,发现 log里 ...

  3. Tomcat通过Redis实现session共享的完整部署记录

    对于生产环境有了一定规模的tomcat集群业务来说,要实现session会话共享,比较稳妥的方式就是使用数据库持久化session.为什么要持久化session(共享session)呢?因为在客户端每 ...

  4. 去掉ambiguous expansion of macro警告

    查看原文:http://www.heyuan110.com/?p=1221 用pod install后,pod工程里出现ambiguous expansion of macro的warning,对于有 ...

  5. Android动画总结

    本文总结常用属性方法等,详细学习可使用如下郭霖大神文章: Android属性动画完全解析(上),初识属性动画的基本用法 Android属性动画完全解析(中),ValueAnimator和ObjectA ...

  6. activiti engine.schema.update DB_SCHEMA_UPDATE_FALSE

    engine.properties # engine propertiesengine.schema.update=trueengine.activate.jobexecutor=falseengin ...

  7. Activiti的BPMN演示工具

    场景是这样的:产品经理不懂技术,又不想安装Java以及Eclipse(需要安装Activiti BPMN Designer的插件). 这两天解决.bpmn的解析(BPMNParser)时顺带找到一个顺 ...

  8. PHP微信支付案例收录

    微信支付API 文档:https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_1&index=1# TP 微信 + 支 ...

  9. 学习 已经登录windows的情况下获取windows的密码

    官网 http://blog.gentilkiwi.com/mimikatz 下载地点 https://github.com/gentilkiwi/mimikatz/releases/latest 使 ...

  10. ubuntu默认壁纸位置

    usr/share/backgrounds和usr/share/wallpapers