传送门

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

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

这时发现直接找带权重心是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. JSP生成WORD文档,EXCEL文档及PDF文档的方法

    转自:https://www.jb51.net/article/73528.htm 本文实例讲述了JSP生成WORD文档,EXCEL文档及PDF文档的方法.分享给大家供大家参考,具体如下: 在web- ...

  2. 19.OGNL与ValueStack(VS)-OGNL入门

    转自:https://wenku.baidu.com/view/84fa86ae360cba1aa911da02.html 下面我们在com.asm.vo.User类中增加一个字段private Ad ...

  3. HTML5拖动

    <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...

  4. oracle imp dmp

    windows>cmd> imp userid=用户名/密码@orcl file=d:\nc60.dmp full=y imp userid=SYSTEM/password@orcl fi ...

  5. libcur+openssl的编译,使之支持SSL<转>

    本机环境: Visual Studio 2010 . Windows 7 64 bit 1: 下载文件 1.1 libcurl: curl-7.49.1.zip 地址: https://curl.ha ...

  6. 22 网络编程--TCP和UDP实现聊天例子

    1.TCP简单的一次对话,单通信 客户端: import socket HOST = 'localhost' PORT = 50006 client = socket.socket(socket.AF ...

  7. React Native指南汇集了各类react-native学习资源、开源App和组件

    来自:https://github.com/ele828/react-native-guide React Native指南汇集了各类react-native学习资源.开源App和组件 React-N ...

  8. [转] #ifndef#define#endif的用法(整理) 原作者:icwk

    文件中的#ifndef 头件的中的#ifndef,这是一个很关键的东西.比如你有两个C文件,这两个C文件都include了同一个头文件.而编译时,这两个C文件要一同编译成一个可运行文件,于是问题来了, ...

  9. mysql 存储过程分页 转载

    /* --名称:MYSQL版查询分页存储过程 by peace 2013-8-14 --输入参数:@fields -- 要查询的字段用逗号隔开 --输入参数:@tables -- 要查询的表 --输入 ...

  10. springmvc获取资源文件的两种方式(超简单)

    1 比如我们在sc目录下新建一个db.properties文件内容如下 DriverClass=com.mysql.jdbc.Driverurl=jdbc:mysql://localhost:3306 ...