这种动态点分治嘛,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. PHP读取Excel文件(PHPExcel)

    /*     * 读取Excel文件     * */    require_once (dirname(dirname(dirname(__FILE__))).'/PHPExcel/PHPExcel ...

  2. Mybatis oracle多表联合查询分页数据重复的问题

    Mybatis oracle多表联合查询分页数据重复的问题 多表联合查询分页获取数据时出现一个诡异的现象:数据总条数正确,但有些记录多了,有些记录却又少了甚至没了.针对这个问题找了好久,最后发现是由于 ...

  3. python模块的打包setuptools

    样例代码:新建test.py文件,内容如下: print "show me" 新建一个setup.py编译文件,内容如下: from distutils.core import s ...

  4. bootstrap-datepicker的简单使用

    先说datepicker. github上的地址是:https://github.com/eternicode/bootstrap-datepicker. 效果如下: 在bundle里面引用添加js ...

  5. 用scala实现一个基于TCP Socket的快速文件传输程序

    这是用scala实现的一个简单的文件传输程序. 服务端 package jpush import java.io.{DataInputStream, File, FileOutputStream} i ...

  6. Delphi中的窗体创建与销毁

    Delphi中的窗体,有模式窗体与非模式窗体两种.两种窗体的调用方式不同,模式窗体使用ShowModal显示,非模式窗体使用Show显示.当显示模式窗体的时候你是不能操作本程序的其他窗体的,你不能把焦 ...

  7. Tomcat配置全攻略

    tomcat的的下载地址http://www.apache.org/dist/jakarta/tomcat-4/ 1.安装jdk,详细操作请参考本站windows 2k和redhat 8.0下java ...

  8. EditText的功能与用法

    EditText与TextView非常相似,它甚至与TextView共用了绝大部分XML属性和方法.EditText和TextView的最大区别在于:EditText可以接受用户输入. EditTex ...

  9. Android常用开发工具的用法

    1.在命令行创建.删除和浏览AVD 在命令行下管理AVD需要借助于android命令(位于Android SDK安装目录的tools子目录下),如果直接执行android子命令将会启动Android ...

  10. easyUI 添加排序到datagrid

    http://www.cnblogs.com/javaexam2/archive/2012/08/10/2632645.html