这种动态点分治嘛,GDKOI时听打到了,也有同学讲到了,所以印象比较深刻也就想出来了,然后就在实现方面卡了好久= =

不得不说CLJ说得真的太简单了,实现方面根本没提。

首先我们可以先用树分治构建出这棵树的分治树,也就是把这棵树的重心作为根节点然后子树为他的子树的重心这样递归下去,然后每个节点存的是其子树的信息。

对于每个节点我们保存这个子树的dv的总和已经把该节点作为点的答案值

这样对于修改能在log n的时间内解决

寻找答案的时候,我们可以发现,如果现在节点的子树dv和*2大于总节点,那么向那个方向过去一定比原方案好

我们先从根节点开始,若发现答案在某棵子树时,我们考虑如何使其儿子节点的答案转变为整个树的答案,可以发现把除这个子树外的所有节点可以缩成一个节点并连在这棵子树上,然后就可以一直这样做下去,找到操作之后再把这些撤销

因此还是得维护一些奇奇怪怪的东西,但打出来还是挺短的

Code:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
#define maxn 100100
typedef long long ll;
typedef pair<ll,ll> ii;
typedef pair<ll,ii> iii;
#define fi first
#define se second
#define pb push_back
struct edges{int to,next,dist;}edge[maxn*];
int l,next[maxn];
inline void addedge(int x,int y,int z) {
edge[++l]=(edges){y,next[x],z};next[x]=l;
edge[++l]=(edges){x,next[y],z};next[y]=l;
}
bool done[maxn];
int s[maxn],f[maxn],root,size;
void dfs(int u,int fa){
s[u]=;f[u]=;
int v=;
for (int i=next[u];i;i=edge[i].next) {
if (done[v=edge[i].to]||v==fa) continue;
dfs(v,u);
s[u]+=s[v];
f[u]=max(f[u],s[v]);
}
f[u]=max(f[u],size-s[u]);
if (f[u]<f[root]) root=u;
}
vector<ii> pre[maxn];
void getdist(int u,int fa,int tar,int dist) {
pre[u].pb(ii(tar,dist));
s[u]=;int v=;
for (int i=next[u];i;i=edge[i].next) {
if (done[v=edge[i].to]||v==fa) continue;
getdist(v,u,tar,dist+edge[i].dist);
s[u]+=s[v];
}
}
vector<iii> ch[maxn];
void work(int u){
done[u]=;
int v=;
pre[u].pb(ii(u,));
for (int i=next[u];i;i=edge[i].next) {
if (done[v=edge[i].to]) continue;
getdist(v,,u,edge[i].dist);
f[]=size=s[v];
dfs(v,root=);
ch[u].pb(iii(root,ii(v,edge[i].dist)));
work(root);
}
}
ll cnt[maxn],sum[maxn];
vector<ll> sumdist[maxn];
inline void update(int x,ll y,ll z){
for (int i=;i<pre[x].size();i++) {
int u=pre[x][i].fi;
cnt[u]+=y;sum[u]+=z+y*pre[x][i].se;
if (i!=pre[x].size()-) {
int j=;
for (;j<ch[u].size();j++)
if (ch[u][j].fi==pre[x][i+].fi) sumdist[u][j]+=z+y*pre[x][i].se;
}
}
}
int realroot;
vector<iii> record;
inline ll query(){
int x=realroot;
int mx=;
record.clear();
while (x){
mx=;
for (int i=;i<ch[x].size();i++)
if (cnt[ch[x][mx].fi]<cnt[ch[x][i].fi]) mx=i;
if (ch[x].size()==||cnt[ch[x][mx].fi]*<=cnt[x]) {
ll ans=sum[x];
for (int i=;i<record.size();i++)
update(record[i].fi,record[i].se.fi,record[i].se.se);
return ans;
}
int v=ch[x][mx].fi;
record.pb(iii(ch[x][mx].se.fi,ii(-(cnt[x]-cnt[v]),
-(sum[x]-sumdist[x][mx]+(cnt[x]-cnt[v])*ch[x][mx].se.se))));
update(ch[x][mx].se.fi,cnt[x]-cnt[v],
sum[x]-sumdist[x][mx]+(cnt[x]-cnt[v])*ch[x][mx].se.se);
x=v;
}
}
int main(){
int n,Q;
scanf("%d%d",&n,&Q);
for (int i=;i<n;i++) {
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
addedge(x,y,z);
}
f[]=size=n;
dfs(,root=);
realroot=root;
work(root);
for (int i=;i<=n;i++) sumdist[i]=vector<ll>(ch[i].size(),);
while (Q--) {
int x,y;
scanf("%d%d",&x,&y);
update(x,y,);
printf("%lld\n",query());
}
return ;
}

BZOJ 3924: [Zjoi2015]幻想乡战略游戏(动态点分治)的更多相关文章

  1. bzoj 3924 [Zjoi2015]幻想乡战略游戏——动态点分治(暴力移动找重心)

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3924 度数只有20,所以从一个点暴力枚举其出边,就能知道往哪个方向走. 知道方向之后直接走到 ...

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

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

  3. 【BZOJ3924】[Zjoi2015]幻想乡战略游戏 动态树分治

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

  4. [BZOJ3924][ZJOI2015]幻想乡战略游戏(动态点分治)

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

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

    \(\color{#0066ff}{ 题目描述 }\) 傲娇少女幽香正在玩一个非常有趣的战略类游戏,本来这个游戏的地图其实还不算太大,幽香还能管得过来,但是不知道为什么现在的网游厂商把游戏的地图越做越 ...

  6. 【bzoj3924】[Zjoi2015]幻想乡战略游戏 动态点分治

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

  7. ZJOI2015 幻想乡战略游戏 动态点分治_树链剖分_未调完

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

  8. BZOJ 3924 / Luogu P3345 [ZJOI2015]幻想乡战略游戏 (动态点分治/点分树)

    题意 树的结构不变,每个点有点权,每一条边有边权,有修改点权的操作,设xxx为树中一点.求∑idist(x,i)∗a[i]\sum_idist(x,i)*a[i]i∑​dist(x,i)∗a[i]的最 ...

  9. bzoj 3924: [Zjoi2015]幻想乡战略游戏

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

随机推荐

  1. scrapy+Lucene搭建小型搜索引擎

    Reference: http://blog.csdn.net/napoay/article/details/51477586 一.选题 工程类搜索型: 定向采集 3-4 个新闻网站, 实现这些网站信 ...

  2. IOS开发-OC学习-Info.plist文件解析

    Info.plist文件是新建ios项目完成后自动生成的一个配置文件,在Xcode中如下图: 通过解析可以获得配置的具体细节,解析过程如下: // 定义一个nsstring用来获取Info.plist ...

  3. EntityFrameWork分页

    EF分页代码 using System; using System.Collections.Generic; using System.Linq; using System.Web; using Sy ...

  4. discuz开发学习

    2014年3月24日 10:36:10 遇到一个问题,discuz 缓存的样式,没有自动生成.后来去后台 进行操作才有效. 解决了之前的遇到的 首页没有套用样式的问题. 现在的问题是 模版的扩展图片 ...

  5. iOS 之 编外知识点

    iOS 使用github iOS 开源库介绍 iOS 优质方案 iOS 开发framework 后端数据库使用 Bomb方案 iOS 错误及解决汇总 后台 之 Bmob 申请苹果企业账号

  6. Python3基础 set() 删除一个列表中的重复项

    镇场诗: 诚听如来语,顿舍世间名与利.愿做地藏徒,广演是经阎浮提. 愿尽吾所学,成就一良心博客.愿诸后来人,重现智慧清净体.-------------------------------------- ...

  7. 要重定向 IO 流,Process 对象必须将 UseShellExecute 属性设置为 False。

    Process  p1= new Process(); p1.StartInfo.UseShellExecute = false;

  8. 基于arm开发板四个按键控制四个灯亮

    基于s5pv2410,cortex a8的四个按键每一个按键点了对应的灯 对于用汇编来编程的话不难,重点在于数据手册,电路图,管脚的看懂 直接上代码 .globl _start_start: ldr ...

  9. Java网络编程总结

    网络编程: 端口: 物理端口: 逻辑端口:用于标识进程的逻辑地址,不同进程的标识:有效端口:0~65535,其中0~1024系统使用或保留端口. java 中ip对象:InetAddress. imp ...

  10. JS基础知识:Javascript事件触发列表

    Javascript是一种由Netscape的LiveScript发展而来的原型化继承的基于对象的动态类型的区分大小写的客户端脚本语言,主要目的是为了解决服务器端语言. JavaScript使我们有能 ...