传送门

题目就是要求维护带权重心。

因此破题的关键点自然就是带权重心的性质。

这时发现直接找带权重心是O(n)的,考虑优化方案。

发现点分树的树高是logn级别的,并且对于以u为根的树,带权重心要么就是u,要么存在于u的某一个儿子为根的子树中。

由于带权重心只有一个,因此只需要从根节点开始向下跳,跳不动了就是答案。

代码:

#include<bits/stdc++.h>
#define N 100005
#define ll long long
using namespace std;
inline int read(){
int ans=0,w=1;
char ch=getchar();
while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
return ans*w;
}
int n,m,siz[N],first[N],lastrt,cnt,tot,sum,rt,vis[N],pa[N],Log[N<<2],fsiz[N];
ll d1[N],d2[N],sumv[N];
struct edge{int v,next,w;}e[N<<1];
inline void Add(int u,int v,int w){e[++cnt].v=v,e[cnt].next=first[u],e[cnt].w=w,first[u]=cnt;}
struct Tree{
int first[N],cnt,tot,st[N<<2][21],d[N],dfn[N];
edge t[N<<1];
inline int min(int a,int b){return a<b?a:b;}
inline void add(int u,int v,int w){t[++cnt].v=v,t[cnt].w=w,t[cnt].next=first[u],first[u]=cnt;}
inline int getdis(int u,int v){
    if(dfn[u]>dfn[v])swap(u,v);
    int tmp=Log[dfn[v]-dfn[u]+1];
    return d[u]+d[v]-2*min(st[dfn[u]][tmp],st[dfn[v]-(1<<tmp)+1][tmp]);
}
inline void dfs(int p,int fa){
    st[(dfn[p]=++tot)][0]=d[p];
    for(int i=first[p];i;i=t[i].next){
        int v=t[i].v;
        if(v==fa)continue;
        d[v]=d[p]+t[i].w;
        dfs(v,p);
        st[++tot][0]=d[p];
    }
}
inline void init(){
    dfs(1,0);
    for(int i=1;(1<<i)<=tot;++i)
        for(int j=1;(1<<i)+j-1<=tot&&j<=tot;++j)
            st[j][i]=min(st[j][i-1],st[j+(1<<(i-1))][i-1]);
}
}T;
inline int max(int a,int b){return a>b?a:b;}
inline void getrt(int p,int fa){
siz[p]=1,fsiz[p]=0;
for(int i=T.first[p];i;i=T.t[i].next){
    int v=T.t[i].v;
    if(vis[v]||v==fa)continue;
    getrt(v,p),siz[p]+=siz[v],fsiz[p]=max(fsiz[p],siz[v]);
}
fsiz[p]=max(fsiz[p],sum-siz[p]);
if(fsiz[p]<fsiz[rt])rt=p;
}
inline void solve(int p,int fa){
vis[p]=1,pa[p]=fa;
for(int i=T.first[p];i;i=T.t[i].next){
    int v=T.t[i].v;
    if(vis[v])continue;
    fsiz[(rt=0)]=sum=siz[v],getrt(v,0),Add(p,rt,v);
    solve(rt,p);
}
}
inline void update(int p,int val){
sumv[p]+=val;
for(int i=p;pa[i];i=pa[i]){
    int dis=T.getdis(pa[i],p);
    d1[pa[i]]+=(ll)dis*val,d2[i]+=(ll)dis*val,sumv[pa[i]]+=val;
}
}
inline ll calc(int p){
ll res=d1[p];
for(int i=p;pa[i];i=pa[i]){
    int dis=T.getdis(pa[i],p);
    res+=d1[pa[i]]-d2[i]+dis*(sumv[pa[i]]-sumv[i]);
}
return res;
}
inline ll query(int p){
ll ans=calc(p);
for(int i=first[p];i;i=e[i].next){
    ll tmp=calc(e[i].w);
    if(tmp<ans)return query(e[i].v);
}
return ans;
}
int main(){
Log[0]=-1,n=read(),m=read();
for(int i=1;i<n;++i){
    int x=read(),y=read(),z=read();
    T.add(x,y,z),T.add(y,x,z);
}
for(int i=1;i<(N<<2);++i)Log[i]=Log[i>>1]+1;
T.init(),sum=n,fsiz[(rt=0)]=n,getrt(1,0),lastrt=rt,solve(rt,0),rt=lastrt;
while(m--){
    int x=read(),y=read();
    update(x,y),cout<<query(rt)<<'\n';
}
return 0;
}

2018.08.28 洛谷P3345 [ZJOI2015]幻想乡战略游戏(点分树)的更多相关文章

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

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

  2. 洛谷P3345 [ZJOI2015]幻想乡战略游戏(动态点分治,树的重心,二分查找,Tarjan-LCA,树上差分)

    洛谷题目传送门 动态点分治小白,光是因为思路不清晰就耗费了不知道多少时间去gang这题,所以还是来理理思路吧. 一个树\(T\)里面\(\sum\limits_{v\in T} D_vdist(u,v ...

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

    传送门 调了两个小时,终于过了-- 凭啥人家代码80行我180行啊!!! 谁叫你大括号换行 谁叫你写缺省源 思路 显然,补给点所在的位置就是这棵树的带权重心. 考虑size已知时如何找重心:一开始设答 ...

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

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

  5. P3345 [ZJOI2015]幻想乡战略游戏

    传送门 考虑先随便找一个点作为根,然后再慢慢移动根,这样一步步走到最优的点 设 $sum[x]$ 表示节点 $x$ 的子树的军队数,$len(x,y)$ 表示 $x,y$ 之间边的长度 那么对于根节点 ...

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

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

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

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

  8. AC日记——[ZJOI2015]幻想乡战略游戏 洛谷 P3345

    [ZJOI2015]幻想乡战略游戏 思路: 树剖暴力转移: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 1 ...

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

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

随机推荐

  1. leetcode108

    /** * Definition for a binary tree node. * public class TreeNode { * public int val; * public TreeNo ...

  2. session失效刷新后登录页面嵌入在iframe中的前台解决办法

    在前台登录页面中加入JS代码,判断登录页面是否在iframe中,在iframe中就跳转出去 例: //判断是否在iframe中,在里面就跳出去 if (top.location.href != loc ...

  3. PCI Simple Communications Controller

    PCI Simple Communications Controller Intel Management Engine Interface (MEI)

  4. 使用.htaccess文件

    禁止对无索引文件的目录进行文件列表展示 默认情况下,当我们访问网站的某个无索引文件(如index.html,index.htm或 index.php)目录时,服务器会显示该目录的文件和子目录列表,这是 ...

  5. Spring Colud 学习

    转自:    http://blog.csdn.net/forezp/article/details/70148833#t0

  6. C#--反射技术

    反射:反射为了动态(比如动态的加载dll,动态创建类型.动态调用方法等) 引用 using System.Reflection 原理: 一个类库编译后会生成一个以.dll结尾的文件,一个以.pdb结尾 ...

  7. vue基础——模板语法

    模板语法介绍 Vue.js使用了基于HTML的模板语法,允许开发者声明式地将dom绑定至底层Vue实例的数据.所有Vue.js的模板都是合法的HTML,所以能被遵循规范的浏览器和HTML解析器解析. ...

  8. 根据img的url 判断img的图片大小

    // 图片地址 后面加时间戳是为了避免缓存 var img_url = 'http://www.qttc.net/static/upload/2013/13643608813441.jpg?'+Dat ...

  9. RISC处理器

     RISC(精简指令集算法)处理器是经过硬件的精简只执行很有限的最常用的那部分指令的处理器.因为通过研究发现,只有 大约 20%的指令是最常用的,把处理器能执行的指令数目减少到 最低限度,对它们的执行 ...

  10. How to Pronounce BEAUTIFUL

    How to Pronounce BEAUTIFUL Share Tweet Share Tagged With: 3-Syllable Can you say this word beautiful ...