题目

P3258 [JLOI2014]松鼠的新家

解析

非常裸的一道树剖题

链上修改+单点查询的板子

记录一下所经过的点\(now[i]\),每次更新\(now[i-1]到now[i]\)

我们链上更新时上一次到的终点,是这一次一次更新的起点,又因为在\(a_n\)处可以不放糖,所以我们每次链上更新完成后,在上条链的终点位置处糖数\(-1\)。

然后套板子直接做

代码

#include <bits/stdc++.h>
using namespace std;
const int N = 2e6 + 10;
int n, m, num, cnt;
int head[N], size[N], f[N], top[N], son[N], dep[N], now[N], id[N];
class node {
public :
int v, nx;
} e[N];
class tree {
public :
int sum, lazy;
int len;
} t[N]; #define lson rt << 1
#define rson rt << 1 | 1 template<class T>inline void read(T &x) {
x = 0; int f = 0; char ch = getchar();
while (!isdigit(ch)) f |= (ch == '-'), ch = getchar();
while (isdigit(ch)) x = x * 10 + ch - '0', ch = getchar();
x = f ? -x : x;
return ;
} inline void add(int u, int v) {
e[++num].nx = head[u], e[num].v = v, head[u] = num;
} void dfs1(int u, int fa) {
size[u] = 1;
for (int i = head[u]; ~i; i = e[i].nx) {
int v = e[i].v;
if (v != fa) {
dep[v] = dep[u] + 1;
f[v] = u;
dfs1(v, u);
size[u] += size[v];
if (size[v] > size[son[u]]) son[u] = v;
}
}
} void dfs2(int u, int t) {
id[u] = ++cnt; top[u] = t;
if (son[u]) dfs2(son[u], t);
for (int i = head[u]; ~i; i = e[i].nx) {
int v = e[i].v;
if (v != f[u] && v != son[u]) dfs2(v, v); //WRONG
}
} inline void pushup(int rt) {
t[rt].sum = t[lson].sum + t[rson].sum;
} void build(int l, int r, int rt) {
t[rt].len = r - l + 1;
if (l == r) return;
int m = (l + r) >> 1;
build(l, m, lson);
build(m + 1, r, rson);
} inline void pushdown(int rt) {
if (t[rt].lazy) {
t[lson].lazy += t[rt].lazy;
t[rson].lazy += t[rt].lazy;
t[lson].sum += t[rt].lazy * t[lson].len;
t[rson].sum += t[rt].lazy * t[rson].len;
t[rt].lazy = 0;
}
} void update(int L, int R, int c, int l, int r, int rt) {
if (L <= l && r <= R) {
t[rt].sum += (t[rt].len * c);
t[rt].lazy += c;
return;
}
pushdown(rt);
int m = (l + r) >> 1;
if (L <= m) update(L, R, c, l, m, lson);
if (R > m) update(L, R, c, m + 1, r, rson);
pushup(rt);
} int query(int L, int R, int l, int r, int rt) {
if (L <= l && r <= R) return t[rt].sum;
pushdown(rt);
int m = (l + r) >> 1, ans = 0;
if (L <= m) ans += query(L, R, l, m, lson);
if (R > m) ans += query(L, R, m + 1, r, rson);
return ans;
} void update_chain(int x, int y, int z) {
int fx = top[x], fy = top[y];
while (fx != fy) {
if (dep[fx] < dep[fy]) swap(fx, fy), swap(x, y);
update(id[fx], id[x], z, 1, cnt, 1);
x = f[fx], fx = top[x];
}
if (id[x] > id[y]) swap(x, y);
update(id[x], id[y], z, 1, cnt, 1);
} int main() {
memset(head, -1, sizeof(head));
read(n);
for (int i = 1, x; i <= n; ++i) read(x), now[i] = x;
for (int i = 1, x, y; i < n; ++i) read(x), read(y), add(x, y), add(y, x);
f[1] = 0, dep[1] = 0;
dfs1(1, 0);
dfs2(1, 1);
build(1, n, 1);
for (int i = 2; i <= n; ++i) update_chain(now[i - 1], now[i], 1), update_chain(now[i], now[i], -1);
for (int i = 1; i <= n; ++i) printf("%d\n", query(id[i], id[i], 1, n, 1));
return 0;
}

最新文章

  1. 当MyEclipse突然异常关闭
  2. 使用MLeaksFinder检测项目中的内存泄露
  3. Unreal Engine4 学习笔记1 状态机 动画蓝图
  4. Docker CPU 资源限制——CPU分片功能测试
  5. hdu 4055 &amp;&amp; hdu 4489 动态规划
  6. 完美实现自己的GetProcAddress函数(转载)
  7. iTiTa再次回归,这一年我们都在干什么?
  8. 创建jira插件
  9. Java 互联网工程师要具备哪些技能或技术?
  10. Android:Asmack能登录但是获取不到联系人的问题
  11. 1--OC -- HelloWorld
  12. [转]ui-grid User can&#39;t select the row by clicking the select checkbox available in the respective row when enableFullRowSelection : true&quot;
  13. &lt;sdoi2017&gt;树点涂色
  14. MySQL 之 mysqlbinlog解析binlog乱码问题解密
  15. 设置https以及http转https的问题
  16. poj 2528(线段树+离散化) 市长的海报
  17. 高效能程序员的七个习惯【csdn】
  18. 利用Maven插件将依赖包、jar/war包及配置文件输出到指定目录
  19. python文件操作,读取,修改,合并
  20. 第一章 程序设计和C语言(笔记)

热门文章

  1. sql查询条件参数为空
  2. [转]JS - Promise使用详解1(基本概念、使用优点)
  3. J-CUBE Appears at AVATAR Xprize at Geneva 2019
  4. 泡泡一分钟:Robust Attitude Estimation Using an Adaptive Unscented Kalman Filter
  5. Maven name=archetypeCatalog value=internal
  6. 微信小程序tabBar底部导航 不显示问题解析
  7. GraphQL漏洞案例之获取Facebook任意用户的朋友列表和部分支付卡详细信息
  8. asp.net core使用水晶报表问题
  9. LinkedHashSet有没有重复的元素
  10. ConcurrentHashMap多线程下比HashTable效率更高