传送门
背景:烁烁很喜欢爬树,这吓坏了树上的皮皮鼠。
题意:
给定一颗nnn个节点的树,边权均为111,初始树上没有皮皮鼠。
烁烁他每次会跳到一个节点uuu,把周围与他距离不超过d的节点各吸引出www只皮皮鼠。皮皮鼠会被烁烁吸引,所以会一直待在节点上不动。
烁烁很好奇,在当前时刻,节点 uuu 有多少个他的好朋友—皮皮鼠。
大意:
给一颗nnn个节点的树,边权均为 111,初始点权均为 000,mmm 次操作:
QQQ xxx:询问 xxx 的点权。
MMM xxx ddd www:将树上与节点 xxx 距离不超过 ddd 的节点的点权均加上 www。

分析

涉及某个点到其它点的路径,且要支持修改,考虑动态点分治
动态点分治这里有详解P6329 【模板】点分树 | 震波【动态点分治】详解

对于这题来说
按照动态点分治,构建出 fatherfatherfather 数组

之后对于每个 QQQ,查询从当前节点开始,往上跳fafafa,找到相对距离不超过 ddd的权值,减去 去重信息 里面的数

对于每个 MMM,同样从当前节点开始,往上跳fafafa,给相对距离不超过 ddd 的节点加上权值,同时更新 去重信息

代码

普通区间加线段树

通过样例详情

//P6329-solve
/*@Author: YooQ
*/
#include <bits/stdc++.h>
using namespace std;
#define sc scanf
#define pr printf
#define ll long long
#define FILE_OUT freopen("out", "w", stdout);
#define FILE_IN freopen("1.in", "r", stdin);
#define debug(x) cout << #x << ": " << x << "\n";
#define AC 0
#define WA 1
#define INF 0x3f3f3f3f
const ll MAX_N = 1e6+5;
const ll MOD = 1e9+7;
int N, M, K;
int head[MAX_N];
int tot = 0;
struct Edge {int to, nxt;
}edge[MAX_N];void addEdge(int u, int v) {edge[tot].nxt = head[u];edge[tot].to = v;head[u] = tot++;edge[tot].nxt = head[v];edge[tot].to = u;head[v] = tot++;
}int parent[MAX_N];
int sz[MAX_N];
int dep[MAX_N];
int top[MAX_N];
int son[MAX_N];void dfs1(int u, int from) {parent[u] = from;dep[u] = dep[from] + 1;son[u] = 0;sz[u] = 1;int v;for (int i = head[u];~i;i=edge[i].nxt) {if ((v=edge[i].to) == from) continue;dfs1(v, u);sz[u] += sz[v];if (sz[v] > sz[son[u]]) {son[u] = v;}}
}void dfs2(int u, int tp) {top[u] = tp;if (son[u]) dfs2(son[u], tp);int v;for (int i = head[u];~i;i=edge[i].nxt) {if ((v=edge[i].to) == son[u] || v == parent[u]) continue;dfs2(v, v);}
}int LCA(int x, int y) {while (top[x] != top[y]) {if (dep[top[x]] < dep[top[y]]) swap(x, y);x = parent[top[x]];}return dep[x] < dep[y] ? x : y;
}int dis(int x, int y) {int lca = LCA(x, y);return dep[x] + dep[y] - 2 * dep[lca];
}int maxx[MAX_N];
bool vis[MAX_N];void root(int u, int from, int& rt, int sum) {sz[u] = 1;maxx[u] = 0;int v;for (int i = head[u];~i;i=edge[i].nxt) {if ((v=edge[i].to) == from || vis[v]) continue;root(v, u, rt, sum);sz[u] += sz[v];maxx[u] = max(maxx[u], sz[v]);}maxx[u] = max(maxx[u], sum - sz[u]);if (maxx[u] < maxx[rt]) {rt = u;}
}int dsz[MAX_N];
int father[MAX_N];void divide(int u, int sum) {vis[u] = 1;dsz[u] = sum;int v;for (int i = head[u];~i;i=edge[i].nxt) {if (vis[v=edge[i].to]) continue;int rt = 0;int vsz = sz[v] < sz[u] ? sz[v] : sum - sz[u];root(v, u, rt, vsz);father[rt] = u;divide(rt, vsz);}
}struct Tr {int k, l, r, add;
}tr[MAX_N<<4];
int indx = 0;int mk() {return ++indx;
}void calc(int& rt, int len, int k) {if (!rt) rt = mk();tr[rt].k += len * k;tr[rt].add += k;
}void push_down(int rt, int l, int r) {if (!tr[rt].add) return;int mid = l + ((r-l)>>1);calc(tr[rt].l, mid - l + 1, tr[rt].add);calc(tr[rt].r, r - mid, tr[rt].add);tr[rt].add = 0;
}void update(int &rt, int l, int r, int x, int y, int k) {if (!rt) rt = mk();if (x <= l && r <= y) {calc(rt, r - l + 1, k);return;}push_down(rt, l, r);int mid = l + ((r-l)>>1);if (x <= mid) update(tr[rt].l, l, mid, x, y, k);if (y  > mid) update(tr[rt].r, mid+1, r, x, y, k);
}int query(int rt, int l, int r, int x) {if (!rt) return 0;if (l == r) {return tr[rt].k;}push_down(rt, l, r);int mid = l + ((r-l)>>1);if (x <= mid) return query(tr[rt].l, l, mid, x);if (x  > mid) return query(tr[rt].r, mid+1, r, x);
}int A[MAX_N], B[MAX_N];void modify(int x, int k, int w) {int d;for (int i = x; i; i = father[i]) {if (dis(x, i) <= k) {update(A[i], 1, dsz[i] + 1, 1, k - dis(x, i) + 1, w);}if (father[i] && dis(x, father[i]) <= k) {update(B[i], 1, dsz[father[i]] + 1, 1, k - dis(x, father[i]) + 1, w);}}
}int ask(int x) {int res = 0;for (int i = x; i; i = father[i]) {res += query(A[i], 1, dsz[i] + 1, dis(x, i) + 1);if (father[i]) res -= query(B[i], 1, dsz[father[i]] + 1, dis(x, father[i]) + 1);}return res;
}int arr[MAX_N];void init() {memset(head, -1, sizeof head);tot = 0;
}void solve(){init();sc("%d%d", &N, &M);int u, v;for (int i = 1; i < N; ++i) {sc("%d%d", &u, &v); addEdge(u, v);}dfs1(1, 0);dfs2(1, 1);int rt = 0;maxx[0] = 1e8;root(1, 0, rt, N);divide(rt, N);char opt[5];int x, y, k;for (int i = 1; i <= M; ++i) {sc("%s", opt);if (*opt == 'M') {sc("%d%d%d", &x, &y, &k);modify(x, y, k);} else {sc("%d", &x);pr("%d\n", ask(x));}}
}signed main()
{#ifndef ONLINE_JUDGEFILE_INFILE_OUT#endifint T = 1;//cin >> T;while (T--) solve();return AC;
}

逻辑上差分优化后的线段树

通过样例结果

//P6329-solve
/*@Author: YooQ
*/
#include <bits/stdc++.h>
using namespace std;
#define sc scanf
#define pr printf
#define ll long long
#define FILE_OUT freopen("out", "w", stdout);
#define FILE_IN freopen("1.in", "r", stdin);
#define debug(x) cout << #x << ": " << x << "\n";
#define AC 0
#define WA 1
#define INF 0x3f3f3f3f
const ll MAX_N = 1e6+5;
const ll MOD = 1e9+7;
int N, M, K;
int head[MAX_N];
int tot = 0;
struct Edge {int to, nxt;
}edge[MAX_N];void addEdge(int u, int v) {edge[tot].nxt = head[u];edge[tot].to = v;head[u] = tot++;edge[tot].nxt = head[v];edge[tot].to = u;head[v] = tot++;
}int parent[MAX_N];
int sz[MAX_N];
int dep[MAX_N];
int top[MAX_N];
int son[MAX_N];void dfs1(int u, int from) {parent[u] = from;dep[u] = dep[from] + 1;son[u] = 0;sz[u] = 1;int v;for (int i = head[u];~i;i=edge[i].nxt) {if ((v=edge[i].to) == from) continue;dfs1(v, u);sz[u] += sz[v];if (sz[v] > sz[son[u]]) {son[u] = v;}}
}void dfs2(int u, int tp) {top[u] = tp;if (son[u]) dfs2(son[u], tp);int v;for (int i = head[u];~i;i=edge[i].nxt) {if ((v=edge[i].to) == son[u] || v == parent[u]) continue;dfs2(v, v);}
}int LCA(int x, int y) {while (top[x] != top[y]) {if (dep[top[x]] < dep[top[y]]) swap(x, y);x = parent[top[x]];}return dep[x] < dep[y] ? x : y;
}int dis(int x, int y) {int lca = LCA(x, y);return dep[x] + dep[y] - 2 * dep[lca];
}int maxx[MAX_N];
bool vis[MAX_N];void root(int u, int from, int& rt, int sum) {sz[u] = 1;maxx[u] = 0;int v;for (int i = head[u];~i;i=edge[i].nxt) {if ((v=edge[i].to) == from || vis[v]) continue;root(v, u, rt, sum);sz[u] += sz[v];maxx[u] = max(maxx[u], sz[v]);}maxx[u] = max(maxx[u], sum - sz[u]);if (maxx[u] < maxx[rt]) {rt = u;}
}int dsz[MAX_N];
int father[MAX_N];void divide(int u, int sum) {vis[u] = 1;dsz[u] = sum;int v;for (int i = head[u];~i;i=edge[i].nxt) {if (vis[v=edge[i].to]) continue;int rt = 0;int vsz = sz[v] < sz[u] ? sz[v] : sum - sz[u];root(v, u, rt, vsz);father[rt] = u;divide(rt, vsz);}
}struct Tr {int k, l, r, add;
}tr[MAX_N<<4];
int indx = 0;int mk() {return ++indx;
}void update(int& rt, int l, int r, int x, int k) {if (!rt) rt = mk();tr[rt].k += k;if (l == r) return;int mid = l + ((r-l)>>1);if (x <= mid) update(tr[rt].l, l, mid, x, k);if (x  > mid) update(tr[rt].r, mid+1, r, x, k);
}int query(int rt, int l, int r, int x) {if (!rt) return 0;if (l == r) {return tr[rt].k;}int mid = l + ((r-l)>>1);if (x <= mid) return tr[tr[rt].r].k + query(tr[rt].l, l, mid, x);if (x  > mid) return query(tr[rt].r, mid+1, r, x);
} int A[MAX_N], B[MAX_N];void modify(int x, int k, int w) {int d;for (int i = x; i; i = father[i]) {if (dis(x, i) <= k) {update(A[i], 1, dsz[i] + 1, k - dis(x, i) + 1, w);}if (father[i] && dis(x, father[i]) <= k) {update(B[i], 1, dsz[father[i]] + 1, k - dis(x, father[i]) + 1, w);}}
}int ask(int x) {int res = 0;for (int i = x; i; i = father[i]) {res += query(A[i], 1, dsz[i] + 1, dis(x, i) + 1);if (father[i]) res -= query(B[i], 1, dsz[father[i]] + 1, dis(x, father[i]) + 1);}return res;
}int arr[MAX_N];void init() {memset(head, -1, sizeof head);tot = 0;
}void solve(){init();sc("%d%d", &N, &M);int u, v;for (int i = 1; i < N; ++i) {sc("%d%d", &u, &v); addEdge(u, v);}dfs1(1, 0);dfs2(1, 1);int rt = 0;maxx[0] = 1e8;root(1, 0, rt, N);divide(rt, N);char opt[5];int x, y, k;for (int i = 1; i <= M; ++i) {sc("%s", opt);if (*opt == 'M') {sc("%d%d%d", &x, &y, &k);modify(x, y, k);} else {sc("%d", &x);pr("%d\n", ask(x));}}
}signed main()
{#ifndef ONLINE_JUDGEFILE_INFILE_OUT#endifint T = 1;//cin >> T;while (T--) solve();return AC;
}

bzoj4372. 烁烁的游戏【动态点分治】相关推荐

  1. [BZOJ4372][烁烁的游戏][动态树分治+线段树+LCA]

    [BZOJ4372][烁烁的游戏][动态树分治+线段树+LCA] 题目大意: 给定一颗nn个节点的树,边权均为11,初始每个点权值为00 . 其中操作QQ xx询问x点的点权,操作 MM xx dd ...

  2. bzoj4372 烁烁的游戏 动态点分治+线段树

    Description 背景:烁烁很喜欢爬树,这吓坏了树上的皮皮鼠. 给定一颗n个节点的树,边权均为1,初始树上没有皮皮鼠. 烁烁他每次会跳到一个节点u,把周围与他距离不超过d的节点各吸引出w只皮皮鼠 ...

  3. BZOJ4372: 烁烁的游戏(动态点分治)

    Description 背景:烁烁很喜欢爬树,这吓坏了树上的皮皮鼠. 题意: 给定一颗n个节点的树,边权均为1,初始树上没有皮皮鼠. 烁烁他每次会跳到一个节点u,把周围与他距离不超过d的节点各吸引出w ...

  4. 【BZOJ4372】烁烁的游戏 动态树分治+线段树

    [BZOJ4372]烁烁的游戏 Description 背景:烁烁很喜欢爬树,这吓坏了树上的皮皮鼠. 题意: 给定一颗n个节点的树,边权均为1,初始树上没有皮皮鼠. 烁烁他每次会跳到一个节点u,把周围 ...

  5. 【bzoj4372】烁烁的游戏 动态点分治+线段树

    题目描述 给一颗n个节点的树,边权均为1,初始点权均为0,m次操作: Q x:询问x的点权. M x d w:将树上与节点x距离不超过d的节点的点权均加上w. 输入 第一行两个正整数:n,m 接下来的 ...

  6. bzoj 4372: 烁烁的游戏 动态点分治_树链剖分_线段树

    [Submit][Status][Discuss] Description 背景:烁烁很喜欢爬树,这吓坏了树上的皮皮鼠. 题意: 给定一颗n个节点的树,边权均为1,初始树上没有皮皮鼠. 烁烁他每次会跳 ...

  7. bzoj 4372 烁烁的游戏 —— 动态点分治+树状数组

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4372 本以为和 bzoj3730 一样,可以直接双倍经验了: 但要注意一下,树状数组不能查询 ...

  8. bzoj 4372 烁烁的游戏——动态点分治+树状数组

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4372 和 bzoj 3070 震波 是一个套路.注意区间修改的话,树状数组不能表示 dis ...

  9. [bzoj4372]烁烁的游戏

    [bzoj4372]烁烁的游戏 动态点分,需要注意的是我们对于每个点要开两个数组,另外一个相当于一个容斥,即把他父亲上的减掉. 代码 #include<bits/stdc++.h> usi ...

  10. BZOJ4372: 烁烁的游戏

    BZOJ4372: 烁烁的游戏 https://lydsy.com/JudgeOnline/problem.php?id=4372 分析: 不是很难想的一道题,用树状数组维护点分树上每一层分治中心的点 ...

最新文章

  1. ul li设置横排,并除去li前的圆点
  2. 【android-tips】如何在android应用中插入百度广告(附源码)
  3. docker WARNING: IPv4 forwarding is disabled. 解决方法
  4. c语言计算机二级资料,2016年计算机二级C语言复习资料汇总
  5. 夜神模拟器模拟安卓测试_使用模拟进行测试
  6. 微信小程序php实现登陆的代码,微信小程序实现微信登录
  7. Spring Boot + Security + Thymeleaf + Activiti 快速开发平台项目
  8. 计算机对医学影像学的作用,医学影像技术中数字图像处理的重要性
  9. PhotoShop的神奇(重新发表)
  10. ipfs+eth部分资料
  11. 【数控雕刻】【刀具路径】北京精雕JDPaint5.19+诺诚NC转换器4.0+SDU NCEdit1.0(什么是ENG和NC文件)
  12. II.MongoDB CRUD Operations(CRUD操作)
  13. 一元云购指定中奖版源码(开源+PC+移动端)
  14. FPS游戏的方框透视+自瞄原理
  15. python尔雅答案_2020尔雅通识课Python》程序设计查题公众
  16. FPGA视频处理系统
  17. Ceph Calamari软件包介绍
  18. 【Spring】IOC:基于注解的IOC容器初始化源码分析
  19. 二十年铸就未来视界 HKC让世界认可中国质造
  20. 学习学习学习学习学习学习学习学习学习学习学习

热门文章

  1. step7设置pcpg_怎么安装STEP7编程软件及PG/PC接口设置
  2. 题目60 相同字母消除法(栈)(ok)
  3. 大厂前端面试都问些什么问题?入职爱奇艺年薪48万,面试经验总结
  4. matlab高斯白噪声功率谱密度,matlab-正弦波-高斯白噪声-均匀白噪声-功率谱密度-自相关函数.doc...
  5. 用Python制作可视化GUI界面,一键实现证件照背景颜色的替换
  6. echarts添加基准线
  7. QQ机器人{应用设计篇}
  8. webp文件_什么是WebP文件(以及如何打开一个文件)?
  9. 华为认证人工智能工程师 HCIA-AI V3.5(中文版) 发布通知
  10. GUI界的大战: QT VS GTK