UOJ261 【NOIP2016】天天爱跑步 LCA+动态开点线段树
UOJ261 【NOIP2016】天天爱跑步
Description
Input
Output
输出1行N 个整数,第个整数表示结点的观察员可以观察到多少人。
Sample Input
2 3
1 2
1 4
4 5
4 6
0 2 5 1 2 3
1 5
1 3
2 6
Sample Output
HINT
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define MAXN 300001
#define MAXM 10000001
using namespace std;
int n, m, w[MAXN], s[MAXN], t[MAXN], lca[MAXN], ans[MAXN];
int tot_e, to[2 * MAXN], nxt[2 * MAXN], pre[MAXN];
void add(int u, int v) { tot_e++, to[tot_e] = v, nxt[tot_e] = pre[u], pre[u] = tot_e; }
int deep[MAXN], fa[MAXN], son[MAXN], size[MAXN];
void dfs(int u, int f, int dep) {
fa[u] = f;
deep[u] = dep;
size[u] = 1;
for (int i = pre[u]; i; i = nxt[i]) {
int v = to[i];
if (v == f)
continue;
dfs(v, u, dep + 1);
size[u] += size[v];
if (size[v] > size[son[u]])
son[u] = v;
}
}
int top[MAXN], dfs_in[MAXN], dfs_out[MAXN], rk[MAXN], dfs_order = 0;
void DFS(int u, int top_chain) {
top[u] = top_chain;
dfs_in[u] = ++dfs_order;
rk[dfs_order] = u;
if (!son[u]) {
dfs_out[u] = dfs_order;
return;
}
DFS(son[u], top_chain);
for (int i = pre[u]; i; i = nxt[i]) {
int v = to[i];
if (v != son[u] && v != fa[u])
DFS(v, v);
}
dfs_out[u] = dfs_order;
}
int LCA(int x, int y) {
while (top[x] != top[y]) {
if (deep[top[x]] < deep[top[y]])
swap(x, y);
x = fa[top[x]];
}
return deep[x] < deep[y] ? x : y;
}
int tot_root = 0, ls[MAXM], rs[MAXM], sum[MAXM], root[MAXM];
void update(int &now, int l, int r, int pos, int val) {
if (!pos)
return;
if (!now)
now = ++tot_root;
sum[now] += val;
if (l == r)
return;
int mid = (l + r) >> 1;
if (pos <= mid)
update(ls[now], l, mid, pos, val);
else
update(rs[now], mid + 1, r, pos, val);
}
int query(int rt, int L, int R, int l, int r) { //[l,r]:目标区间,[L,R]:总区间
if (!rt)
return 0;
if (L == l && r == R)
return sum[rt];
int mid = (L + R) >> 1;
if (r <= mid)
return query(ls[rt], L, mid, l, r);
else if (l > mid)
return query(rs[rt], mid + 1, R, l, r);
else
return query(ls[rt], L, mid, l, mid) + query(rs[rt], mid + 1, R, mid + 1, r);
}
int main() {
scanf("%d%d", &n, &m);
for (int i = 1, u, v; i < n; i++) {
scanf("%d%d", &u, &v);
add(u, v), add(v, u);
}
for (int i = 1; i <= n; i++) scanf("%d", &w[i]);
dfs(1, 0, 1);
DFS(1, 0);
for (int i = 1; i <= m; i++) {
scanf("%d%d", &s[i], &t[i]);
lca[i] = LCA(s[i], t[i]);
}
for (int i = 1; i <= m; i++) {
update(root[deep[s[i]]], 1, n, dfs_in[s[i]], 1);
update(root[deep[s[i]]], 1, n, dfs_in[fa[lca[i]]], -1);
}
for (int i = 1; i <= n; i++)
ans[i] = query(root[deep[i] + w[i]], 1, n, dfs_in[i], dfs_out[i]);
tot_root = 0;
memset(ls, 0, sizeof(ls));
memset(rs, 0, sizeof(rs));
memset(sum, 0, sizeof(sum));
memset(root, 0, sizeof(root));
for (int i = 1; i <= m; i++) {
update(root[deep[s[i]] - 2 * deep[lca[i]] + 2 * n], 1, n, dfs_in[t[i]], 1);
update(root[deep[s[i]] - 2 * deep[lca[i]] + 2 * n], 1, n, dfs_in[lca[i]], -1);
}
for (int i = 1; i <= n; i++) ans[i] += query(root[w[i] - deep[i] + 2 * n], 1, n, dfs_in[i], dfs_out[i]);
for (int i = 1; i <= n; i++) printf("%d ", ans[i]);
puts("");
return 0;
}
UOJ261 【NOIP2016】天天爱跑步 LCA+动态开点线段树的更多相关文章
- [Vani有约会]雨天的尾巴——树上差分+动态开点线段树合并
题目描述 首先村落里的一共有n座房屋,并形成一个树状结构.然后救济粮分m次发放,每次选择两个房屋(x,y),然后对于x到y的路径上(含x和y)每座房子里发放一袋z类型的救济粮. 然后深绘里想知道,当所 ...
- LG4556 [Vani有约会]雨天的尾巴 动态开点线段树+线段树合并
问题描述 LG4556 题解 对于每一个结点,建立一棵动态开点线段树. 然后自低向上合并线段树. 同时维护整个值域的最大值和最大值位置. \(\mathrm{Code}\) #include<b ...
- [ZJOI2019]语言(树链剖分+动态开点线段树+启发式合并)
首先,对于从每个点出发的路径,答案一定是过这个点的路径所覆盖的点数.然后可以做树上差分,对每个点记录路径产生总贡献,然后做一个树剖维护,对每个点维护一个动态开点线段树.最后再从根节点开始做一遍dfs, ...
- [2016湖南长沙培训Day4][前鬼后鬼的守护 chen] (动态开点线段树+中位数 or 动规 or 贪心+堆优化)
题目大意 给定一个长度为n的正整数序列,令修改一个数的代价为修改前后两个数的绝对值之差,求用最小代价将序列转换为不减序列. 其中,n满足小于500000,序列中的正整数小于10^9 题解(引自mzx神 ...
- [bzoj 3531][SDOI2014]旅行(树链剖分+动态开点线段树)
题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3531 分析: 对于每个颜色(颜色<=10^5)都建立一颗线段树 什么!那么不是M ...
- 【BZOJ-4636】蒟蒻的数列 动态开点线段树 ||(离散化) + 标记永久化
4636: 蒟蒻的数列 Time Limit: 30 Sec Memory Limit: 256 MBSubmit: 247 Solved: 113[Submit][Status][Discuss ...
- codeforces 893F - Physical Education Lessons 动态开点线段树合并
https://codeforces.com/contest/893/problem/F 题意: 给一个有根树, 多次查询,每次查询对于$x$i点的子树中,距离$x$小于等于$k$的所有点中权值最小的 ...
- codeforces 915E - Physical Education Lessons 动态开点线段树
题意: 最大$10^9$的区间, $3*10^5$次区间修改,每次操作后求整个区间的和 题解: 裸的动态开点线段树,计算清楚数据范围是关键... 经过尝试 $2*10^7$会$MLE$ $10^7$会 ...
- CF915E Physical Education Lessons 动态开点线段树
题目链接 CF915E Physical Education Lessons 题解 动态开点线段树 代码 /* 动态开点线段树 */ #include<cstdio> #include&l ...
随机推荐
- [JZOJ3233] 照片
题目 题目大意 有一个\(01\)序列.给你一堆区间,每个区间中有且仅有一个\(1\)点. 问最多的\(1\)点个数. 思考历程 感觉这题特别经典,似乎在哪里见过,又好像没有见过. 一开始朝贪心方面想 ...
- 【JZOJ6367】工厂(factory)
description 大神 wyp 开了家工厂,工厂有 n 个工人和 p 条流水线. 工厂的工人都是睡神,因此第 i 个工人只会在 si 至 ti 时刻才会工作. 每个工人都会被分派到一条流水线上, ...
- PHP缓存技术的应用1
// 自定义缓存类 class Cache_Filesystem { // 缓存写保存 function set ($key, $data, $ttl) { //打开文件为读/写模式 $h = fop ...
- hadoop快照管理
快照相当于对目录做备份,并不会复制所有文件,而是记录文件的变化命令用法 ()hdfs dfsadmin -allowSnapshot 路径 (开启指定目录的快照功能) ()hdfs dfsadmin ...
- springboot启动报 A child container failed during start 错误解决过程
启动结果如下: "C:\Program Files\Java\jdk1.8.0_201\bin\java.exe" -agentlib:jdwp=transport=dt_sock ...
- openstack各组件介绍
Nova:计算服务,通过虚拟化技术,实现虚拟机的创建,管理,删除,是openstack中最核心的服务. Neutron:网络服务,为虚拟机提供网络连接服务,就像物理机的交换机和路由器一样 Glance ...
- Python3升级3.6强力Django+杀手级xadmin打造在线教育平台✍✍✍
Python3升级3.6强力Django+杀手级xadmin打造在线教育平台 教程 Xadmin安装方法: settings.py 的配置: users App 下的 adminx.py 的配置:
- HttpServletRequest的方法详细说明
1.Java 部分request.getHeader()详细说明 == JAVA 部分request.getHeader() 详细说明== System.out.println("rotoc ...
- [WPF自定义控件]?使用WindowChrome自定义Window Style
原文:[WPF自定义控件]?使用WindowChrome自定义Window Style 1. 为什么要自定义Window 对稍微有点规模的桌面软件来说自定义的Window几乎是标配了,一来设计师总是克 ...
- C#真他妈神奇,一个函数都不用写就能实现一个简单的邮件发送工具
MailMessage EmaillMessage = new MailMessage( //创建一个对象 new MailAddress(loning.Te ...