[COJ0970]WZJ的数据结构(负三十)

试题描述

给你一棵N个点的无根树,点和边上均有权值。请你设计一个数据结构,回答M次操作。

1 x v:对于树上的每一个节点y,如果将x、y在树上的距离记为d,那么将y节点的权值加上d*v。

2 x:询问节点x的权值。

输入

第一行为一个正整数N。
第二行到第N行每行三个正整数ui,vi,wi。表示一条树边从ui到vi,距离为wi。
第N+1行为一个正整数M。
最后M行每行三个或两个正整数,格式见题面。

输出

对于每个询问操作,输出答案。

输入示例


输出示例


数据规模及约定

对于30%的数据:1<=N,M<=1000
另有50%的数据:1<=N,M<=100000,保证修改操作均在询问操作之前。
对于100%的数据:1<=N,M<=100000,1<=x<=N,1<=v,wi<=1000

题解

新姿势 get:动态点分治。

其实我也不知道为啥叫“动态”点分治。

首先这道题可以转化一下,对于每个节点我们不直接记录题目要求的答案,我们可以把修改操作转化成“给节点 x 的权值加上 v”,那么询问就变成了“求树上所有点到节点 x 的加权距离(就是对于所有的节点 u 求 sigma( D[u] · dist(u, x) ),这里的 D[u] 表示节点 u 的权值,dist(a, b) 表示树上路径 (a, b) 的边权总和)”。注意到边权永远是固定的。

我们可以建立出“重心树”,就是先点分治一波,然后我们把每一层分治的中心连到一块形成的新的树形结构。然后我们维护这棵树的子树信息:val[u] 表示节点 u 为根的子树中点权和;distv[u] 表示节点 u 的子树中所有点到 u 的加权距离和(注意这里加权距离是在原树上的);distfa[u] 表示节点 u 的子树中所有到 fa[u] 的加权距离和(注意这里加权距离是在原树上的,而 fa[u] 是重心树上 u 的父亲结点)。

然后我们就发现每次修改和询问都是可以 O(logn) 实现的。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
using namespace std; int read() {
int x = 0, f = 1; char c = getchar();
while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
return x * f;
} #define maxn 100010
#define maxm 200010
#define maxlog 19
#define LL long long int n, m, head[maxn], nxt[maxm], to[maxm], dist[maxm]; void AddEdge(int a, int b, int c) {
to[++m] = b; dist[m] = c; nxt[m] = head[a]; head[a] = m;
swap(a, b);
to[++m] = b; dist[m] = c; nxt[m] = head[a]; head[a] = m;
return ;
} int dep[maxn], mnd[maxlog][maxn<<1], Log[maxn<<1], clo, pos[maxn];
void build(int u, int pa) {
mnd[0][pos[u] = ++clo] = dep[u];
for(int e = head[u]; e; e = nxt[e]) if(to[e] != pa)
dep[to[e]] = dep[u] + dist[e], build(to[e], u), mnd[0][++clo] = dep[u];
return ;
}
void rmq_init() {
Log[1] = 0;
for(int i = 2; i <= clo; i++) Log[i] = Log[i>>1] + 1;
for(int j = 1; (1 << j) <= clo; j++)
for(int i = 1; i + (1 << j) - 1 <= clo; i++)
mnd[j][i] = min(mnd[j-1][i], mnd[j-1][i+(1<<j-1)]);
return ;
}
int cdist(int a, int b) {
int ans = dep[a] + dep[b];
int l = pos[a], r = pos[b];
if(l > r) swap(l, r);
int t = Log[r-l+1];
return ans - (min(mnd[t][l], mnd[t][r-(1<<t)+1]) << 1);
} int rt, size, f[maxn], siz[maxn];
bool vis[maxn];
void getroot(int u, int pa) {
siz[u] = 1; f[u] = 0;
for(int e = head[u]; e; e = nxt[e]) if(to[e] != pa && !vis[to[e]]) {
getroot(to[e], u);
siz[u] += siz[to[e]];
f[u] = max(f[u], siz[to[e]]);
}
f[u] = max(f[u], size - siz[u]);
if(f[rt] > f[u]) rt = u;
return ;
}
int fa[maxn];
void solve(int u) {
vis[u] = 1;
for(int e = head[u]; e; e = nxt[e]) if(!vis[to[e]]) {
f[rt = 0] = size = siz[u]; getroot(to[e], u);
fa[rt] = u; solve(rt);
}
return ;
} int val[maxn];
LL distv[maxn], distfa[maxn];
void update(int s, int v) {
for(int u = s; u; u = fa[u]) {
val[u] += v;
if(fa[u]) {
int d = cdist(fa[u], s);
distv[fa[u]] += (LL)d * v;
distfa[u] += (LL)d * v;
}
// printf("%d: %lld %lld\n", u, distv[u], distfa[u]);
}
return ;
}
LL query(int s) {
LL ans = distv[s];
for(int u = s; fa[u]; u = fa[u])
ans += distv[fa[u]] - distfa[u] + (LL)(val[fa[u]] - val[u]) * cdist(fa[u], s);
return ans;
} int main() {
n = read();
for(int i = 1; i < n; i++) {
int a = read(), b = read(), c = read();
AddEdge(a, b, c);
} build(1, 0); rmq_init();
f[rt = 0] = size = n; getroot(1, 0);
solve(rt);
// for(int i = 1; i <= n; i++) printf("%d(%d)%c", fa[i], i, i < n ? ' ' : '\n'); int q = read();
while(q--) {
int tp = read(), u = read();
if(tp == 1) {
int v = read();
update(u, v);
}
if(tp == 2) printf("%lld\n", query(u));
} return 0;
}

[COJ0970]WZJ的数据结构(负三十)的更多相关文章

  1. COJ966 WZJ的数据结构(负三十四)

    WZJ的数据结构(负三十四) 难度级别:C: 运行时间限制:20000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 给一棵n个节点的树,请对于形如"u  ...

  2. COJ970 WZJ的数据结构(负三十)

    WZJ的数据结构(负三十) 难度级别:D: 运行时间限制:1000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 给你一棵N个点的无根树,点和边上均有权值.请你设计 ...

  3. COJ968 WZJ的数据结构(负三十二)

    WZJ的数据结构(负三十二) 难度级别:D: 运行时间限制:5000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 给你一棵N个点的无根树,边上均有权值,每个点上有 ...

  4. COJ 0970 WZJ的数据结构(负三十)树分治

    WZJ的数据结构(负三十) 难度级别:D: 运行时间限制:1000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 给你一棵N个点的无根树,点和边上均有权值.请你设计 ...

  5. [COJ0968]WZJ的数据结构(负三十二)

    [COJ0968]WZJ的数据结构(负三十二) 试题描述 给你一棵N个点的无根树,边上均有权值,每个点上有一盏灯,初始均亮着.请你设计一个数据结构,回答M次操作. 1 x:将节点x上的灯拉一次,即亮变 ...

  6. COJ 1003 WZJ的数据结构(三)ST表

    WZJ的数据结构(三) 难度级别:B: 运行时间限制:3000ms: 运行空间限制:51200KB: 代码长度限制:2000000B 试题描述 请你设计一个数据结构,完成以下功能: 给定一个大小为N的 ...

  7. 数据结构(三十四)最短路径(Dijkstra、Floyd)

    一.最短路径的定义 在网图和非网图中,最短路径的含义是不同的.由于非网图没有边上的权值,所谓的最短路径,其实就是指两顶点之间经过的边数最少的路径:而对于网图来说,最短路径是指两顶点之间经过的边上权值之 ...

  8. 数据结构(三十二)图的遍历(DFS、BFS)

    图的遍历和树的遍历类似.图的遍历是指从图中的某个顶点出发,对图中的所有顶点访问且仅访问一次的过程.通常有两种遍历次序方案:深度优先遍历和广度优先遍历. 一.深度优先遍历 深度优先遍历(Depth_Fi ...

  9. COJ986 WZJ的数据结构(负十四)

    WZJ的数据结构(负十四) 难度级别:D: 运行时间限制:6000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 请你设计一个数据结构,完成以下功能: 给定一个大小 ...

随机推荐

  1. tabBar隐藏方式

    如果是从A push到B,并且把A的一个东西传到B,那么在push时就要隐藏tabBar,并且要在B ViewController设置一个接收A传到的属性. 这种方式一般用在表格点选,要把表格点选的内 ...

  2. PHP autoload实践

    本文目的 本文简要的描述了PHP提供的autoload机制,以及在scake中使用实践.用于减少不必要的文件包含,提高php系统性能. 什么是__autoload php是脚本语言,不同于c++只需要 ...

  3. android开发学习 ------- volley网络请求的实例

    在  http://www.sojson.com/httpRequest/  上对http进行访问,将此访问在android中的应用 ********************************* ...

  4. Oracle分区表例子

    分区表 Oracle提供的分区方法有以下几种. 1.范围分区(range) 范围分区是应用范围比较广的表分区方式,它是以列的值的范围来作为分区的划分条 件,将记录存放到列值所在的 range分区中. ...

  5. Spring框架学习-搭建第一个Spring项目

    步骤一:下载Spring开发包. 官网:https://spring.io/           下载地址:https://repo.spring.io/libs-release-local/org/ ...

  6. mysql 忘记密码 登陆+修改密码

    step1: 苹果->系统偏好设置->最下边点mysql 在弹出页面中 关闭mysql服务(点击stop mysql server) step2: 进入终端输入:cd /usr/local ...

  7. 键盘工具栏的快速集成--IQKeyboardManager

    转自:http://www.cnblogs.com/gaoxiaoniu/p/5333187.html 键盘工具栏的快速集成--IQKeyboardManager IQKeyboardManager, ...

  8. [转帖]4412开发板/4418开发板Android4.4.4实现ble功能

    本文转自迅为论坛:http://bbs.topeetboard.com ①.4418开发板实现ble功能方法: 在4418/android/device/nexell/drone2/device.mk ...

  9. Swift 性能相关

    起初的疑问源自于「在 Swift 中的, Struct:Protocol 比 抽象类 好在哪里?」.但是找来找去都是 Swift 性能相关的东西.整理了点笔记,供大家可以参考一下. 一些疑问 在正题开 ...

  10. charsets - 程序员对字符集和国际化的观点

    描述 Linux 是一个国际性的操作系统.它的各种各样实用程序和设备驱动程序 (包括控制台驱动程序 ) 支持多种语言的字符集,包括带有附加符号的拉丁字母表字符,重音符,连字(字母结合), 和全部非拉丁 ...