2018.08.28 洛谷P3345 [ZJOI2015]幻想乡战略游戏(点分树)
传送门
题目就是要求维护带权重心。
因此破题的关键点自然就是带权重心的性质。
这时发现直接找带权重心是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]幻想乡战略游戏(点分树)的更多相关文章
- 洛谷 P3345 [ZJOI2015]幻想乡战略游戏 解题报告
P3345 [ZJOI2015]幻想乡战略游戏 题目描述 傲娇少女幽香正在玩一个非常有趣的战略类游戏,本来这个游戏的地图其实还不算太大,幽香还能管得过来,但是不知道为什么现在的网游厂商把游戏的地图越做 ...
- 洛谷P3345 [ZJOI2015]幻想乡战略游戏(动态点分治,树的重心,二分查找,Tarjan-LCA,树上差分)
洛谷题目传送门 动态点分治小白,光是因为思路不清晰就耗费了不知道多少时间去gang这题,所以还是来理理思路吧. 一个树\(T\)里面\(\sum\limits_{v\in T} D_vdist(u,v ...
- 洛谷P3345 [ZJOI2015]幻想乡战略游戏 [动态点分治]
传送门 调了两个小时,终于过了-- 凭啥人家代码80行我180行啊!!! 谁叫你大括号换行 谁叫你写缺省源 思路 显然,补给点所在的位置就是这棵树的带权重心. 考虑size已知时如何找重心:一开始设答 ...
- bzoj3924 [Zjoi2015]幻想乡战略游戏 点分树,动态点分
[BZOJ3924][Zjoi2015]幻想乡战略游戏 Description 傲娇少女幽香正在玩一个非常有趣的战略类游戏,本来这个游戏的地图其实还不算太大,幽香还能管得过来,但是不知道为什么现在的网 ...
- P3345 [ZJOI2015]幻想乡战略游戏
传送门 考虑先随便找一个点作为根,然后再慢慢移动根,这样一步步走到最优的点 设 $sum[x]$ 表示节点 $x$ 的子树的军队数,$len(x,y)$ 表示 $x,y$ 之间边的长度 那么对于根节点 ...
- P3345 [ZJOI2015]幻想乡战略游戏 动态点分治
\(\color{#0066ff}{ 题目描述 }\) 傲娇少女幽香正在玩一个非常有趣的战略类游戏,本来这个游戏的地图其实还不算太大,幽香还能管得过来,但是不知道为什么现在的网游厂商把游戏的地图越做越 ...
- BZOJ 3924 / Luogu P3345 [ZJOI2015]幻想乡战略游戏 (动态点分治/点分树)
题意 树的结构不变,每个点有点权,每一条边有边权,有修改点权的操作,设xxx为树中一点.求∑idist(x,i)∗a[i]\sum_idist(x,i)*a[i]i∑dist(x,i)∗a[i]的最 ...
- AC日记——[ZJOI2015]幻想乡战略游戏 洛谷 P3345
[ZJOI2015]幻想乡战略游戏 思路: 树剖暴力转移: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 1 ...
- [ZJOI2015]幻想乡战略游戏——动态点分治
[ZJOI2015]幻想乡战略游戏 带修改下,边点都带权的重心 随着变动的过程中,一些子树内的点经过会经过一些公共边.考虑能不能对这样的子树一起统计. 把树上贡献分块. 考虑点分治算法 不妨先把题目简 ...
随机推荐
- leetcode504
public class Solution { public string ConvertToBase7(int num) { ? "" : "-"; var ...
- leetcode292
public class Solution { public bool CanWinNim(int n) { //如果要赢,最后3个必须是自己来拿 //也就是最后剩1,2,3是胜利, //如果剩4枚, ...
- shell echo 打印换行
echo -e "aaaaaaaaaaaaaaaaa\nbbbbbbbbbbbbbb"
- oracle跟踪sql语句
oracle跟踪sql语句 select * from v$sql 查询客户端电脑名称的ID select terminal, SID,SERIAL# from v$session where ( ...
- PYTHON-进阶-装饰器小结,转载
本文转载自:http://www.wklken.me/posts/2012/10/27/python-base-decorator.html 基本概念 具体概念自己google 装饰器是一个很著名的设 ...
- Lodash踩坑记录
一直在用lodash 这个框架,最近踩了一个坑 reverse 这个函数是mutable的 ,后边去查了文档 Note: This method mutates array and is based ...
- rook 记录
更改rook 集群的配置 https://github.com/rook/rook/blob/master/design/cluster-update.md rook集群升级流程 https://ro ...
- Fb,tw等emoji相关
最近处理fb emoji,查了下相关的资料.记录于此 twitter blog 关于:https://blog.twitter.com/developer/en_us/a/2014/open-sou ...
- Subquery typo with using in(转)
Subquery typo with using in Do you use the following syntax? SELECT * FROM TABLE WHERE COLUMN IN ( ...
- Partial Tree(DP)
Partial Tree http://acm.hdu.edu.cn/showproblem.php?pid=5534 Time Limit: / MS (Java/Others) Memory Li ...