[NOIp2016]天天爱跑步

LG传送门

作为一道被毒瘤出题人们玩坏了的NOIp经典题,我们先不看毒瘤的“动态爱跑步”和“天天爱仙人掌”,回归一下本来的味道。

对于一个人,他的路程会分为两段,一段向上(根),一段向下,考虑在向上过程中他能产生贡献的观察者具有什么性质:设出发点深度为\(dep[x]\),观察者深度为\(dep[y]\),观察的时间为\(t\),需满足\(dep[x] - dep[y] = t\),换句话说就是\(dep[y] + t = dep[x]\)。向下那一段的推导类似,下面的部分也只以向上的路径为例来解释。

现在我们记录每个点下方出发点深度为\(dep[x]\)的人数,需要对于每个出发点更新出发点到出发点与目的地的lca的所有点,想到到开一颗权值线段树,用线段树合并不断把信息往上传,在lca处消除这次更新的影响,这样一来直接我们就可以在树上统计答案了。向下路径的处理与向上路径类似,这里就不再赘述,上代码。

#include <cstdio>
#include <cctype>
#include <vector>
#define R register
#define I inline
#define B 1000000
using namespace std;
const int N = 300001, M = 15000007;
char buf[B], *p1, *p2;
I char gc() { return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, B, stdin), p1 == p2) ? EOF : *p1++; }
I int rd() {R int f = 0;R char c = gc();while (c < 48 || c > 57)c = gc();while (c > 47 && c < 58)f = f * 10 + (c ^ 48), c = gc();return f;
}
int w[N], s[N], t[N], p[N], q[N], d[N], r[N], u[N], v[N], o[N], n, C, S;
struct T{int f, p, q;}e[M];
vector <int> g[N];
I void swp(int &x, int &y) { x ^= y, y ^= x, x ^= y; }
void dfs1(int x, int f) {p[x] = f, d[x] = d[f] + 1, t[x] = 1;for (R int i = 0, y, m = 0; i < s[x]; ++i)if ((y = g[x][i]) ^ f) {dfs1(y, x), t[x] += t[y];if (t[y] > m)m = t[y], q[x] = y;}
}
void dfs2(int x, int t) {r[x] = t;if (q[x])dfs2(q[x], t);for (R int i = 0, y; i < s[x]; ++i)if ((y = g[x][i]) ^ p[x] && y ^ q[x])dfs2(y, y);
}
I int lca(int x, int y) {while (r[x] ^ r[y]) {if (d[r[x]] < d[r[y]])swp(x, y);x = p[r[x]];}if (d[x] > d[y])swp(x, y);return x;
}
void ins(int &k, int l, int r, int x, int v) {if (!k)k = ++C;e[k].f += v;if (l == r)return ;R int m = l + r >> 1;if (x <= m)ins(e[k].p, l, m, x, v);elseins(e[k].q, m + 1, r, x, v);
}
int mrg(int k, int t) {if (!k)return t;if (!t)return k;e[k].f += e[t].f, e[k].p = mrg(e[k].p, e[t].p), e[k].q = mrg(e[k].q, e[t].q);return k;
}
int qry(int k, int l, int r, int x) {if (l == r)return e[k].f;R int m = l + r >> 1;if (x <= m)return qry(e[k].p, l, m, x);elsereturn qry(e[k].q, m + 1, r, x);
}
void dfs(int x) {for (R int i = 0, y; i < s[x]; ++i)if ((y = g[x][i]) ^ p[x])dfs(y), u[x] = mrg(u[x], u[y]), v[x] = mrg(v[x], v[y]);o[x] = qry(u[x], 1, S, w[x] + d[x]) + qry(v[x], 1, S, w[x] - d[x] + n);
}
int main() {R int m, i, x, y, a;n = rd(), m = rd(), S = n << 1;for (i = 1; i < n; ++i)x = rd(), y = rd(), g[x].push_back(y), g[y].push_back(x);for (i = 1; i <= n; ++i)s[i] = g[i].size(), w[i] = rd();dfs1(1, 0), dfs2(1, 1);for (i = 1; i <= m; ++i)x = rd(), y = rd(), a = lca(x, y), ins(u[x], 1, S, d[x], 1), ins(u[a], 1, S, d[x], -1), ins(v[y], 1, S, d[x] - (d[a] << 1) + n, 1), ins(v[p[a]], 1, S, d[x] - (d[a] << 1) + n, -1);dfs(1);for (i = 1; i <= n; ++i)printf("%d ", o[i]);return 0;
}

因为减的结果可能有负数,所以加上一个\(n\),值域变两倍。

转载于:https://www.cnblogs.com/cj-chd/p/10353138.html

[NOIp2016]天天爱跑步 线段树合并相关推荐

  1. BZOJ 4719: [Noip2016]天天爱跑步 线段树合并

    title BZOJ 4719 LUOGU 1600 简化题意: 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.<天天爱跑步>是一个养成类游戏,需要玩家每 ...

  2. NOIP2016 天天爱跑步 线段树合并

    题意: 给出一棵n个点的树,以及m次操作,每次操作从起点向终点以每秒一条边的速度移动(初始时刻为0),最后对于每个点询问有多少次操作在经过该点的时刻为某值. (题面太毒瘤建议自己去题库食用) 分析: ...

  3. 【NOIP2016】【桶/线段树合并】【树上差分】天天爱跑步

    [题目描述] [思路] 这是道好题呀.考虑把一条路径(u,v)拆成两条:从u到lca(u,v),从lca(u,v)到v.下面我们以向上的路径为例讨论做法.对于一条向上的路径,它对一个点x有贡献当且仅当 ...

  4. [noip2016]天天爱跑步(主席树+lca)

    恩..在百度的第一页翻了翻,没有用主席树做的,于是打算水一篇blog: 天天爱跑步 首先有一个解题的关键: 将玩家的向上和向下分成两部分: 先定义几个变量,s是起点,t是终点,wi是每个观察员出现的时 ...

  5. [2021.1.27多校省选模拟10]跑步(线段树合并)

    [2021.1.27多校省选模拟10]跑步 经典的树上启发式合并题目,维护对应子树的从当前点到子树内一个节点这个链待定,其他部分已经确定的方案数,这个东西按照对应点到根节点的路径点权和为下标存在一个权 ...

  6. NOIP2016天天爱跑步

    NOIP2016天天爱跑步 这题一看显然lca+树上差分,但是因为有w的限制不能直接加,所以考虑权值线段树合并, 每个选手的起点终点对于不同的节点的影响是不同的,这就非常麻烦了,但是可以发现无论如何他 ...

  7. 线段树合并:从入门到放弃

    感谢这篇博客(这里跳转)以及邱宇大神的讲解,我也算作入门(自闭)了. 需要掌握的前置知识点:动态开点线段树.权值线段树. 一.合并思想 线段树合并,就是指建立一颗新的线段树,保存原有的两颗线段树的信息 ...

  8. [NOIP2016]天天爱跑步 题解(树上差分) (码长短跑的快)

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

  9. 线段树合并(四道例题)

    顾名思义,就是合并两个同构(就是维护的区间长度一样)线段树,其实也没啥比较nb的算法,就是一个一个节点的合并,但是如果在n个要合并的线段树里,如果一共有m个元素,则配合动态开点,复杂度会均摊成一个惊人 ...

最新文章

  1. php数组包含对象吗,在包含数组的PHP对象上调用方法
  2. 2012需要分析的一些技术(1)
  3. android游戏画面抖动,抖音游戏主播是怎么直播手机画面的?
  4. JNI 实战全面解析
  5. xml教程之约束schema
  6. P4587-[FJOI2016]神秘数【主席树】
  7. OpenWrt 之 MT7628 移植第三方SPI驱动
  8. conda : 无法将“conda”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,如果包括路径,请确保路径正确,然后再试一 次。
  9. uni-app 开发微信,支付宝小程序
  10. Oracle分析函数之Rank函数
  11. Haar特征分类器和AdaBoost算法
  12. python之常用标准库
  13. 计算机管理用户拒绝访问,win10系统管理员账户拒绝访问怎么办
  14. ST大宗商品订货系统源码.net语言
  15. C#如何在Windows上接入蓝牙设备
  16. webstorm 光标换行快捷键
  17. centos 安装、配置metis
  18. python中finally是什么意思_什么是pythontry-finally语句?它能起到什么样的作用?
  19. 卖掉房子去做理财可取吗?
  20. C语言 找第一个只出现一次的字符

热门文章

  1. 商业信息敏感、安全处理(口令、数字证书-U盾-密保卡、指纹识别-虹膜识别)...
  2. Learning to Rank算法介绍:GBRank
  3. java读写文件总结
  4. Apache无法正常启动的原因
  5. 【零基础学Java】—哈希值(四十一)
  6. 【操作系统】—进程的状态与转换
  7. 【博客项目】—Joi(八)
  8. 灰度拉伸python_灰度变换之灰度线性拉伸(算法1)
  9. 为什么民营银行,农村商业银行存款,定期存款利率比五大行还高?
  10. 幼儿园的孩子怎么才可以锻炼其自理能力呢?