这题可以用线段树做,不过正解恐怕是动态点分治?(点分树)

简单介绍下动态点分治的概念:在点分治的过程中,一般我们面对的问题都是静态的。如果涉及到修改这类的操作,我们就希望找到我们是如何处理到当前的修改点的,换而言之,我们希望记录下点分治的过程,这样可以通过爬点分树等操作消除影响。

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

这样对于修改能在$O(logn)的时间内解决

简要看下题意:询问树的带权重心,加修改。

如果不加修改,找到树的重心就是一个树形dp的傻题。

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

考虑如何处理修改?

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

下面是咸鱼给出的一些实现细节:

1.跟虚树一样(不知道的可以百度“世界树”),这也是要在第二棵树上对原树进行统计,所以一定千万小心不要弄混,我学到的办法是对原树进行封装,这样即使不小心访问错了他也会给你提示。

2.对树进行欧拉序遍历可以利用rmq在$O(1)$查询LCA,这点也是特别好懂的。(只会树剖的蒟蒻瑟瑟发抖)

代码总共113行,应该是可读性比较好的。

zyz的那个码风清奇根本不能看啊QAQ

应该是目前比较能看的点分树代码之一吧。

#include<bits/stdc++.h>
#define N 100010
typedef long long ll;
using namespace std;
int n,m,x,y,z,size[N],tot;
int head[N],sum,rt,f[N],vis[N],par[N],cnt,lg[N<<];
ll dis1[N],dis2[N],sumv[N];
struct Edge{int u,v,next,w;}G[*N];
void Addedge(int u,int v,int w){
G[++tot].u=u;G[tot].v=v;G[tot].w=w;G[tot].next=head[u];head[u]=tot;
}
struct Orinal_Tree{
int head[N],cnt,tot;
int st[N<<][],dis[N],tpos[N<<];
struct edge{int u,v,next,w;}E[*N];
inline void addedge(int u,int v,int w){
E[++tot].u=u;E[tot].v=v;E[tot].w=w;E[tot].next=head[u];head[u]=tot;
E[++tot].u=v;E[tot].v=u;E[tot].w=w;E[tot].next=head[v];head[v]=tot;
}
inline int getdis(int u,int v){
if(tpos[u]>tpos[v])swap(u,v);
int k=lg[tpos[v]-tpos[u]+];
return dis[u]+dis[v]-*min(st[tpos[u]][k],st[tpos[v]-(<<k)+][k]);
}
void dfs(int u,int fa){
st[++cnt][]=dis[u];tpos[u]=cnt;
for(int i=head[u];i;i=E[i].next){
int v=E[i].v;if(v==fa)continue;
dis[v]=dis[u]+E[i].w;
dfs(v,u);
st[++cnt][]=dis[u];
}
}
inline void initrmq(){
memset(tpos,,sizeof(tpos));cnt=;tot=;dis[]=;
dfs(,);
for(int j=;(<<j)<=cnt;j++)
for(int i=;i+(<<j)-<=cnt&&i<=cnt;i++)
st[i][j]=min(st[i][j-],st[i+(<<(j-))][j-]);
}
}T;
void getroot(int u,int fa){
size[u]=;f[u]=;
for(int i=T.head[u];i;i=T.E[i].next){
int v=T.E[i].v;if(vis[v]||v==fa)continue;
getroot(v,u);size[u]+=size[v];
f[u]=max(f[u],size[v]);
}
f[u]=max(f[u],sum-size[u]);
if(f[u]<f[rt])rt=u;
}
void work(int u,int fa){
vis[u]=;par[u]=fa;//printf("%d\n",u);puts("!!!");
for(int i=T.head[u];i;i=T.E[i].next){
int v=T.E[i].v;if(vis[v])continue;
sum=size[v];f[]=size[v];rt=;
getroot(v,);Addedge(u,rt,v);
work(rt,u);
}
}
inline void ins(int u,int val){
sumv[u]+=val;
for(int i=u;par[i];i=par[i]){
int dist=T.getdis(par[i],u);
dis1[par[i]]+=(ll)dist*val;
dis2[i]+=(ll)dist*val;
sumv[par[i]]+=val;
}
}
inline ll calc(int u){
ll ans=dis1[u];
for(int i=u;par[i];i=par[i]){
int dist=T.getdis(par[i],u);
ans+=dis1[par[i]]-dis2[i];
ans+=dist*(sumv[par[i]]-sumv[i]);
}
return ans;
}
ll query(int u){
ll ans=calc(u);//printf("%lld\n",ans);
for(int i=head[u];i;i=G[i].next){
ll tmp=calc(G[i].w);
if(tmp<ans)return query(G[i].v);
}
return ans;
}
inline int read(){
int f=,x=;char ch;
do{ch=getchar();if(ch=='-')f=-;}while(ch<''||ch>'');
do{x=x*+ch-'';ch=getchar();}while(ch>=''&&ch<='');
return f*x;
}
void init(){
memset(dis1,,sizeof(dis1));
memset(dis2,,sizeof(dis2));
memset(sumv,,sizeof(sumv));
lg[]=-;
for (int i=;i<(N<<);i++)lg[i]=lg[i>>]+;
n=read();m=read();//printf("%d %d\n",n,m);
for (int i=;i<n;i++)
x=read(),y=read(),z=read(),T.addedge(x,y,z);
}
int main(){
init();T.initrmq();sum=n;f[]=n;
rt=;getroot(,);
int LastOrder=rt;work(rt,);rt=LastOrder;
//for(int i=1;i<=20;i++)//printf("%d ",T.head[i]);puts("");
for(int i=;i<=m;i++){
x=read();y=read();ins(x,y);
printf("%lld\n",query(rt));
}
return ;
}

【bzoj3924&&luogu3345】幻想乡战略游戏的更多相关文章

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

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

  2. BZOJ3924 ZJOI2015 幻想乡战略游戏 【动态点分治】

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

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

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

  4. BZOJ3924 [Zjoi2015]幻想乡战略游戏

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

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

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

  6. BZOJ3924——[Zjoi2015]幻想乡战略游戏

    0.题意:动态维护带权中心 1.分析:妈的,这题做了一天,mdzzzzzzzzzzzzzzzzzz-.. 这个题是边权,我们首先要将边权转化成点权... 我们维护一个分支结构中到根的距离和,一个分支结 ...

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

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

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

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

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

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

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

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

随机推荐

  1. (原创)像极了爱情的详解排序二叉树,一秒get

    排序二叉树(建立.查找.删除) 二叉树我们已经非常熟悉了,但是除了寻常的储存数据.遍历结构,我们还能用二叉树做什么呢? 我们都知道不同的遍历方式会对相同的树中产生不同的序列结果,排序二叉树就是利用二叉 ...

  2. 小旭讲解 LeetCode 53. Maximum Subarray 动态规划 分治策略

    原题 Given an integer array nums, find the contiguous subarray (containing at least one number) which ...

  3. Ubuntu 常见错误及解决方法——长期不定时更新

    1. 修复 /etc/sudoers 文件损坏导致不能使用 sudo 命令 这是之前错误地编辑了 /etc/sudoers 这个文件导致的,因此撤销编辑即可,但由于已经不能使用 sudo 命令,因此不 ...

  4. [PocketFlow]解决TensorFLow在COCO数据集上训练挂起无输出的bug

    1. 引言 因项目要求,需要在PocketFlow中添加一套PeleeNet-SSD和COCO的API,具体为在datasets文件夹下添加coco_dataset.py, 在nets下添加pelee ...

  5. pta编程(1-8)

    知识点:本次编程运用到的格式 #include<stdio.h> int main(void) { printf(); return 0; } 过程:1-3.没什么问题,就是注意字符的输入 ...

  6. Eclipse下JRebel6.5.0热部署插件安装、破解及配置

    发现一个问题:如果安装了jRebel,但是并未对项目添加jRebel监听时,如果重写jar包中的类, 虽然重写后的类会得到编译(classes中的class已经是修改后的class),但是并不会调用重 ...

  7. hdu 2199 Can you solve this equation? (二分法)

    Can you solve this equation? Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K ( ...

  8. hihoCoder #1872 : Pythagorean triple

    此题是 2018 年 ICPC Asia Beijing Regional Contest 的 C 题. 题目大意 求斜边长度不超过 $n$($ n \le 10^9$) 的勾股数的数量.不计两直角边 ...

  9. [洛谷P2210]Haywire

    题目大意:有$n(n\leqslant12)$个数,每个数和其他三个数连边,求一个排列,使得边的长度最小 题解:状压$DP$,$f_{i,j}$表示当前确定的数状态为$i$,有$j$条边起点被确定终点 ...

  10. 【CF MEMSQL 3.0 D. Third Month Insanity】

    time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standa ...