http://www.lydsy.com/JudgeOnline/problem.php?id=3924

gty的测试题,不会动态点分治而且看不出来链剖做法而且暴力打残所以这道题喜闻乐见的爆零了qwq

动态点分治:设重心重构树上以x为根的子树为\(T_x\),在重心重构树上每个点维护3个值。

\(sum(x)=\sum\limits_{u\in T_x}d(u)\)

\(ans(x)=\sum\limits_{u\in T_x}d(u)*dis(u,x)\)

\(ans\_fa(x)=\sum\limits_{u\in T_x}d(u)*dis(u,fa(x))\)

其中,\(dis\)指的是原树上的两点间距离,这个可以用st表\(O(1)\)求出;\(fa(x)\)指的是重心重构树上x的父亲。

每次修改x时,在重心重构树上不断地往上跳同时维护这三个值就可以了。

要查询一个点的花费(这里的花费指的在整棵树上的花费),类似修改,从重心重构树上不断地往上跳并统计答案(\(ans\_fa\)很明显是用来减掉自身贡献的)。

查询时从重心重构树的树根开始,枚举当前点在原树上连向更小分治块的边,检查这些边直接连着的点的花费。要是没有比当前点小的,答案就是当前点的花费;否则当前点跳到此时花费最小的点所在的下一级分治块的重心,继续检查。

感性理解:因为任意一条链上的点的花费是单峰的(峰向下),每次都向峰靠拢,所以这么做是正确的。

又因为重心重构树的树高是\(O(\log n)\)的,查询一个点的花费的时间复杂度是\(O(\log n)\),所以总时间复杂度是\(O(n\log n+q\log^2n*d)\)。

d指的是检查的所有点的平均度数,因为cls原题面中说明了每个点的度不超过20,所以这样可过。

这道题适合做动态点分治的模板题啊qwq

#include<vector>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N = 100003; namespace RE {
struct node {int nxt, to, w;} E[N];
int cnt = 0, point[N], fa[N];
ll sum[N], ans[N], ans_fa[N];
void ins(int u, int v) {E[++cnt] = (node) {point[u], v}; point[u] = cnt; fa[v] = u;}
} namespace ORG {
struct node {int nxt, to, w;} E[N << 1];
int cnt = 0, point[N];
bool vis[N];
vector <pair <int, int> > ref[N];
void ins(int u, int v, int e) {E[++cnt] = (node) {point[u], v, e}; point[u] = cnt;} int qu[N], fa[N], sz[N];
int findrt(int x) {
fa[qu[1] = x] = 0;
int p = 0, q = 1, u;
while (p != q) {
sz[u = qu[++p]] = 0;
for (int i = point[u]; i; i = E[i].nxt)
if (E[i].to != fa[u] && !vis[E[i].to])
fa[E[i].to] = u, qu[++q] = E[i].to;
} for (int i = q; i >= 1; --i) {
sz[fa[qu[i]]] += (++sz[qu[i]]);
if ((sz[qu[i]] << 1) > q)
return qu[i];
}
} int root;
void dfs(int x) {
vis[x] = true;
for (int i = point[x]; i; i = E[i].nxt)
if (!vis[E[i].to]) {
root = findrt(E[i].to);
ref[x].push_back(make_pair(E[i].to, root));
RE::ins(x, root);
dfs(root);
}
} int L[N], wat[N << 1], tt = 0;
ll f[N << 1][19], deep[N]; void dfs2(int x, int ff) {
wat[L[x] = ++tt] = x;
for (int i = point[x]; i; i = E[i].nxt)
if (E[i].to != ff) {
deep[E[i].to] = deep[x] + E[i].w;
dfs2(E[i].to, x);
wat[++tt] = x;
}
} int Log_2[N << 1], rt;
void pre() {
dfs2(1, 0);
Log_2[1] = 0; int cc = 0;
for (int i = 2; i <= tt; ++i) {
Log_2[i] = cc;
if ((1 << (cc + 1)) == i)
++cc;
}
for (int i = 1; i <= tt; ++i)
f[i][0] = deep[wat[i]];
for (int j = 1; j <= 18; ++j)
for (int i = (1 << j); i <= tt; ++i)
f[i][j] = min(f[i][j - 1], f[i - (1 << (j - 1))][j - 1]); rt = 1; while (RE::fa[rt]) rt = RE::fa[rt];
} int len;
ll dis(int x, int y) {
ll r = deep[x] + deep[y];
x = L[x]; y = L[y];
if (x > y) x ^= y ^= x ^= y;
len = Log_2[y - x + 1];
ll dlca = min(f[y][len], f[x - 1 + (1 << len)][len]);
return r - (dlca << 1);
} ll query(int x) {
ll ret = RE::ans[x], retf;
int ff, tmp = x;
while (true) {
if ((ff = RE::fa[tmp]) == 0) return ret;
retf = RE::ans[ff] - RE::ans_fa[tmp];
ret += retf + (RE::sum[ff] - RE::sum[tmp]) * dis(x, ff);
tmp = ff;
}
} void change(int x, int e) {
int tmp = x;
while (true) {
RE::sum[tmp] += e;
RE::ans[tmp] += dis(x, tmp) * e;
if (RE::fa[tmp]) {
RE::ans_fa[tmp] += dis(x, RE::fa[tmp]) * e;
tmp = RE::fa[tmp];
} else
return;
}
} ll ansit() {
int tmp = rt, an = tmp, len;
pair <int, int> ann;
ll annow, cmpan, rr;
while (true) {
cmpan = annow = query(tmp);
for (int i = 0, len = ref[tmp].size(); i < len; ++i)
if ((rr = query(ref[tmp][i].first)) < annow)
annow = rr, ann = ref[tmp][i];
if (annow != cmpan)
tmp = ann.second;
else
return annow;
}
}
} int n; int main() {
int q;
scanf("%d%d", &n, &q);
int u, v, e;
for (int i = 1; i < n; ++i) {
scanf("%d%d%d", &u, &v, &e);
ORG::ins(u, v, e);
ORG::ins(v, u, e);
} ORG::dfs(ORG::findrt(1));
ORG::pre(); while (q--) {
scanf("%d%d", &u, &e);
ORG::change(u, e);
printf("%lld\n", ORG::ansit());
}
return 0;
}

【BZOJ 3924】【ZJOI 2015】幻想乡战略游戏的更多相关文章

  1. [ZJOI 2015]幻想乡战略游戏

    Description 傲娇少女幽香正在玩一个非常有趣的战略类游戏,本来这个游戏的地图其实还不算太大,幽香还能管得过来,但是不知道为什么现在的网游厂商把游戏的地图越做越大,以至于幽香一眼根本看不过来, ...

  2. 【BZOJ 3924】[Zjoi2015]幻想乡战略游戏

    题目: 题解: 对点分树理解加深了233,膜拜zzh干翻紫荆花. 感谢zzh的讲解. 首先优化基于传统DP,假设树不发生变化,我们就可以利用DP求出带权重心. 考虑修改,我们思路不变,还是从root开 ...

  3. ZJOI 2015 幻想乡战略游戏(动态点分治)

    题意 https://loj.ac/problem/2135 思路 首先要明确一点,答案分布是有单调性的.什么意思呢?假设我们的答案在 \(u\) 节点,\((u,v)\) 之间有一条边且 \(u\) ...

  4. 解题:ZJOI 2015 幻想乡战略游戏

    题面 神**所有点都爆int,我还以为我写出什么大锅了,不开long long见祖宗... 动态点分治利用点分树树高不超过log的性质,我们对每个点维护一个子树和,一个点分树子树和,一个点分树上父亲的 ...

  5. bzoj3924 [Zjoi2015]幻想乡战略游戏 点分树,动态点分

    [BZOJ3924][Zjoi2015]幻想乡战略游戏 Description 傲娇少女幽香正在玩一个非常有趣的战略类游戏,本来这个游戏的地图其实还不算太大,幽香还能管得过来,但是不知道为什么现在的网 ...

  6. 【BZOJ3924】幻想乡战略游戏(动态点分治)

    [BZOJ3924]幻想乡战略游戏(动态点分治) 题面 权限题...(穷死我了) 洛谷 题解 考虑不修改 发现一个贪心的做法 假设当前放在当前位置 如果它有一个子树的兵的总数大于总数的一半 那么,放到 ...

  7. LOJ2135 「ZJOI2015」幻想乡战略游戏

    题意 题目描述 傲娇少女幽香正在玩一个非常有趣的战略类游戏,本来这个游戏的地图其实还不算太大,幽香还能管得过来,但是不知道为什么现在的网游厂商把游戏的地图越做越大,以至于幽香一眼根本看不过来,更别说和 ...

  8. LOJ #2135. 「ZJOI2015」幻想乡战略游戏

    #2135. 「ZJOI2015」幻想乡战略游戏 链接 分析: 动态点分治,求加权重心,带修改. 考虑如果知道了一个点s,如何求答案,那么首先可以点分治的思想,求每个联通块内所有点到分治中心距离和,然 ...

  9. 洛谷 P3345 [ZJOI2015]幻想乡战略游戏 解题报告

    P3345 [ZJOI2015]幻想乡战略游戏 题目描述 傲娇少女幽香正在玩一个非常有趣的战略类游戏,本来这个游戏的地图其实还不算太大,幽香还能管得过来,但是不知道为什么现在的网游厂商把游戏的地图越做 ...

  10. [ZJOI2015]幻想乡战略游戏——动态点分治

    [ZJOI2015]幻想乡战略游戏 带修改下,边点都带权的重心 随着变动的过程中,一些子树内的点经过会经过一些公共边.考虑能不能对这样的子树一起统计. 把树上贡献分块. 考虑点分治算法 不妨先把题目简 ...

随机推荐

  1. word-wrap word-break 区别

    word-wrap word-break 区别 word-break * word-break:break-all;//直接把单词截断 * word-break:break-word;//虽然单词截断 ...

  2. Python面向对象学习2(面向对象的语法和特性,待更新)

    上一个内容我们介绍了面向对象和面向对象场景现在我们来学习下语法和特性 1,面向对象基本语法: # -*- coding:utf-8 -*- # Author: Colin Yao class Dog( ...

  3. 理解js中私有变量

    私有变量在js中是个什么概念.当下我的认识是var所定义的变量,实际可以理解为属性和方法,或者单单是临时存储器,不归属任何对象. 一个声明函数: function a(){  var v = &quo ...

  4. PKUWC 2019 自闭记

    PKUWC 2019 自闭记 Day -1 考前天天在隔壁的物竞教室划水(雀魂,能和吉老师一起玩的游戏都是好游戏),没有做题. Day 0 早上8:16的高铁,到广州南居然要6个小时...不知道福州和 ...

  5. 虚拟机出现intel vt -x 处于禁用状态打不开处理方式

    处理方式 . 1 进入bios 以华硕主板为例 进入高级模式找到cpu虚拟技术 打开虚拟技术支持 其它电脑找到这个

  6. python基础===字符串的制表,换行基础操作

    \n\t 制表符和换行符 >>> print("Languages:\n\tPython\n\tC\n\tJavaScript") Languages: Pyth ...

  7. 异步网络模块之aiohttp的使用(一)

    异步网络模块之aiohttp的使用(一) 平时我们也许用的更多的是requests模块,或者是requests_hml模块,但是他们都属于阻塞类型的不支持异步,速度很难提高,于是后来出现了异步的gre ...

  8. selenium WebElement 的属性和方法 属性

    tag_name 标签名,例如 'a'表示<a>元素get_attribute(name) 该元素name 属性的值text 该元素内的文本,例如<span>hello< ...

  9. linux命令--head

    head 与 tail 就像它的名字一样的浅显易懂,它是用来显示开头或结尾某个数量的文字区块,head 用来显示档案的开头至标准输出中,而 tail 想当然尔就是看档案的结尾. 具体使用参考链接: h ...

  10. JMeter 中 HTTP Cookie 管理器的使用

    根据 web 应用的复杂度你可以选择创建两种类型的 JMeter 测试计划:面向点击数的或面向场景的. 创建一个面向点击数的测试计划你需要有中值统计.这些统计要包含你的应用每秒应该处理多少个独立请求的 ...