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. 20151024_001_C#基础知识(静态与非静态的区别,值类型和引用类型,堆和栈的区别,字符串的不可变性,命名空间)

    1:我们把这些具有相同属性和相同方法的对象进行进一步的封装,抽象出来类这个概念. 类就是个模子,确定了对象应该具有的属性和方法. 对象是根据类创建出来的. 2:类:语法 [public] class ...

  2. win10以前连接过的wifi密码怎么查看

    右键点击开始,在菜单中选择打开命令提示符,以管理员的权限打开.  然后输入命令netsh wlan show profile显示以前此电脑连接过的所有WIFI记录配置信息.    确定要查看的WIFI ...

  3. hdu 1081 To The Max(dp+化二维为一维)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1081 To The Max Time Limit: 2000/1000 MS (Java/Others ...

  4. hdu 1879 继续畅通工程 (并查集+最小生成树)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1879 继续畅通工程 Time Limit: 2000/1000 MS (Java/Others)    ...

  5. 2017-2018-1 《Linux内核原理与设计》第十二周作业

    <linux内核原理与设计>第十二周作业 Sql注入基础原理介绍 分组: 和20179215袁琳完成实验 一.实验说明   SQL注入攻击通过构建特殊的输入作为参数传入Web应用程序,而这 ...

  6. Low overhead memory space management

    Methods, apparatus, and systems, including computer programs encoded on a computer storage medium, m ...

  7. android 内核调试

    这篇文档给出使用android emulator 和 arm-linux-androideabi-gdb 调试 android kernel 的方法 1. checkout goldfish 源码: ...

  8. Linux C中内联汇编的语法格式及使用方法(Inline Assembly in Linux C)【转】

    转自:http://www.linuxidc.com/Linux/2013-06/85221p3.htm 阅读Linux内核源码或对代码做性能优化时,经常会有在C语言中嵌入一段汇编代码的需求,这种嵌入 ...

  9. perl操作MongoDB

    perl操作MongoDB http://blog.csdn.net/jophyyao/article/details/8223190 Mongodb 的C语言操作 http://blog.csdn. ...

  10. BZOJ 2002: [Hnoi2010]Bounce 弹飞绵羊 动态树

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2002 题意:加边,删边,查询到根的距离. #include <bits/stdc++ ...