【BZOJ 3924】[Zjoi2015]幻想乡战略游戏
题目:

题解:
对点分树理解加深了233,膜拜zzh干翻紫荆花。
感谢zzh的讲解。
首先优化基于传统DP,假设树不发生变化,我们就可以利用DP求出带权重心。
考虑修改,我们思路不变,还是从root开始找,但发现这样会被卡成$n^2$,原因是每次经过点太多,为了优化,考虑点分树,由于点分树的性质使得假设我们可以在点分树上找到最优解,那么每次最多经过$log$个节点,可以保证时间复杂度。
然后考虑在点分树转移,假设当前节点为x,我们枚举其在原树中的边,假设当前枚举边的另一端为y,那么由DP可以得出如果以当前边分为两半,若y的一半点权和大于所有点权的一半,那么最优解一定在y那边存在,然后我们由点分树直接跳跃到y对应的块中。若不存在这样的y,则x一定为最优解。
这样的话我们的目的就是求x点对应的答案以及y一边对应的点权和,我们用三个数组来记录当前x的点分子树的点权和,点分子树到达x的$d*dis$和,以及到达其父亲的$d*dis$和,这样统计x的答案就可以在$log$的时间内完成。
对于y我们可以开一个$log$大小的数组来记录在点分数上走过的点,并按照原树dfs排序,每次到达一个新的x用$log$更新,并在此序列上维护一个$sum$表示经过路径上x与其儿子s点权和之差,那么考虑若枚举的y是x在原树的儿子或父亲时的情况,分类讨论,利用$sum$快速求出y一边的点权和。
综上所述,时间复杂度为$O(20nlog_2^nlog_2^{log_2^n})$
代码:
#define Troy
#define inf 0x7fffffff #include "bits/stdc++.h" using namespace std; inline int read(){
int s=,k=;char ch=getchar();
while (ch<''|ch>'') ch=='-'?k=-:,ch=getchar();
while (ch>&ch<='') s=s*+(ch^),ch=getchar();
return s*k;
} const int N=1e5+; typedef long long ll; struct edges {
int v,nv,w;edges *last;
}edge[N<<],*head[N];int cnt; inline void push(int u,int v,int w){
edge[++cnt]=(edges){v,,w,head[u]};head[u]=edge+cnt;
} int bit[]; class ST{
public:
inline void build(int *a,int n){
lgs[]=-;
register int i,j;
for (i=;i<=n;++i) lgs[i]=lgs[i>>]+,f[i][]=a[i];
for (i=;bit[i]<=n;++i)
for (j=;j+bit[i]<=n+;++j)
f[j][i]=min(f[j][i-],f[j+bit[i-]][i-]);
} inline int query(int l,int r){
if(r<l) swap(l,r);int t=lgs[r-l+];
return min(f[l][t],f[r-bit[t]+][t]);
}
private:
int f[N<<][],lgs[N<<];
}RMQ; int dis[N],eular[N<<],num,beg[N],End[N],n,m; inline void DFS(int x,int fa){
eular[beg[x]=++num]=dis[x];
for(edges *i=head[x];i;i=i->last) if(i->v^fa){
dis[i->v]=dis[x]+i->w;
DFS(i->v,x);
eular[++num]=dis[x];
}End[x]=num;
} inline ll get_dis(int x,int y){
return dis[x]+dis[y]-(RMQ.query(beg[x],beg[y])<<);
} class Point_Divide_Tree{
public:
int root,tot,fat[N],size[N],heavy[N],dsum[N];
bool vis[N];
ll dissum[N],fdissum[N]; inline void dfs(int x,int fa){
size[x]=,heavy[x]=;
for(edges *i=head[x];i;i=i->last) if(i->v!=fa&&!vis[i->v]){
dfs(i->v,x),size[x]+=size[i->v];
heavy[x]=max(heavy[x],size[i->v]);
}heavy[x]=max(heavy[x],tot-size[x]);
if(heavy[root]>heavy[x]) root=x;
} inline void build(int x,int fa){
root=,dfs(x,);
vis[x=root]=true,fat[x]=fa,dfs(x,x);
for (edges *i=head[x];i;i=i->last) if(!vis[i->v]){
tot=size[i->v];
build(i->v,x),i->nv=root;
}root=x;
} inline void insert(int x,int y,int val){
tot+=val;
while(x){
dsum[x]+=val;
dissum[x]+=get_dis(x,y)*val;
if(fat[x])
fdissum[x]+=get_dis(fat[x],y)*val;
x=fat[x];
}
} ll ans,sum[];
int pos[],leth; inline int calc(int fa,int x,int real){
int ret=dsum[real];
if(dis[x]<dis[fa]){
int l=lower_bound(pos+,pos+leth+,beg[fa])-pos,
r=upper_bound(pos+,pos+leth+,End[fa])-pos-;
ret+=sum[leth]-sum[r]+sum[l-];
}else{
int l=lower_bound(pos+,pos+leth+,beg[x])-pos,
r=upper_bound(pos+,pos+leth+,End[x])-pos-;
ret+=sum[r]-sum[l-];
}
return ret;
} inline ll calc(int x){
ll ret=dissum[x];
int p=x;
while(fat[x]){
ret+=(dsum[fat[x]]-dsum[x])*get_dis(fat[x],p)+dissum[fat[x]]-fdissum[x];
x=fat[x];
}return ret;
} inline void update(int x,int y){
ll now=dsum[x]-dsum[y];
for(int i=leth+;i;--i){
sum[i]=sum[i-]+now;
if(i==||pos[i-]<=beg[x]){
pos[i]=beg[x];
break;
}else pos[i]=pos[i-];
}++leth;
} inline void query(int x){
for(edges *i=head[x];i;i=i->last) if(i->nv){
if(calc(x,i->v,i->nv)*>=tot){
update(x,i->nv);
ans=calc(i->nv);
query(i->nv);
break;
}
}
} inline void query(){
leth=;
ans=dissum[root];
query(root);
printf("%lld\n",ans);
}
}tree; int main(){
register int i,j;
for (i=;i<=;++i) bit[i]=<<i;
n=read(),m=read();
for (i=;i^n;++i){
int a=read(),b=read(),c=read();
push(a,b,c),push(b,a,c);
}
DFS(,),RMQ.build(eular,num);
tree.tot=n,tree.heavy[]=inf;
tree.build(,),tree.tot=;
while(m--){
i=read(),j=read();
tree.insert(i,i,j);
tree.query();
}
}
【BZOJ 3924】[Zjoi2015]幻想乡战略游戏的更多相关文章
- bzoj 3924: [Zjoi2015]幻想乡战略游戏
Description 傲娇少女幽香正在玩一个非常有趣的战略类游戏,本来这个游戏的地图其实还不算太大,幽香还能管得过来,但是不知道为什么现在的网游厂商把游戏的地图越做越大,以至于幽香一眼根本看不过来, ...
- bzoj 3924 [Zjoi2015]幻想乡战略游戏——动态点分治(暴力移动找重心)
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3924 度数只有20,所以从一个点暴力枚举其出边,就能知道往哪个方向走. 知道方向之后直接走到 ...
- BZOJ 3924 ZJOI2015 幻想乡战略游戏 树链剖分
题目链接:https://www.luogu.org/problemnew/show/P3345(bzoj权限题) 题意概述:动态维护树的上所有点到这棵树的带权重心的距离和.N,Q<=10000 ...
- BZOJ 3924: [Zjoi2015]幻想乡战略游戏(动态点分治)
这种动态点分治嘛,GDKOI时听打到了,也有同学讲到了,所以印象比较深刻也就想出来了,然后就在实现方面卡了好久= = 不得不说CLJ说得真的太简单了,实现方面根本没提. 首先我们可以先用树分治构建出这 ...
- bzoj3924 [Zjoi2015]幻想乡战略游戏 点分树,动态点分
[BZOJ3924][Zjoi2015]幻想乡战略游戏 Description 傲娇少女幽香正在玩一个非常有趣的战略类游戏,本来这个游戏的地图其实还不算太大,幽香还能管得过来,但是不知道为什么现在的网 ...
- 洛谷 P3345 [ZJOI2015]幻想乡战略游戏 解题报告
P3345 [ZJOI2015]幻想乡战略游戏 题目描述 傲娇少女幽香正在玩一个非常有趣的战略类游戏,本来这个游戏的地图其实还不算太大,幽香还能管得过来,但是不知道为什么现在的网游厂商把游戏的地图越做 ...
- [ZJOI2015]幻想乡战略游戏——动态点分治
[ZJOI2015]幻想乡战略游戏 带修改下,边点都带权的重心 随着变动的过程中,一些子树内的点经过会经过一些公共边.考虑能不能对这样的子树一起统计. 把树上贡献分块. 考虑点分治算法 不妨先把题目简 ...
- BZOJ3924 ZJOI2015 幻想乡战略游戏 【动态点分治】
BZOJ3924 ZJOI2015 幻想乡战略游戏 Description 傲娇少女幽香正在玩一个非常有趣的战略类游戏,本来这个游戏的地图其实还不算太大,幽香还能管得过来,但是不知道为什么现在的网游厂 ...
- AC日记——[ZJOI2015]幻想乡战略游戏 洛谷 P3345
[ZJOI2015]幻想乡战略游戏 思路: 树剖暴力转移: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 1 ...
- 【BZOJ3924】[Zjoi2015]幻想乡战略游戏 动态树分治
[BZOJ3924][Zjoi2015]幻想乡战略游戏 Description 傲娇少女幽香正在玩一个非常有趣的战略类游戏,本来这个游戏的地图其实还不算太大,幽香还能管得过来,但是不知道为什么现在的网 ...
随机推荐
- 《转》iOS 平台 Cocos2d-x 项目接入新浪微博 SDK 的坑
最近在做一个 iOS 的 cocos2d-x 项目接入新浪微博 SDK 的时候被“坑”了,最后终于顺利的解决了.发现网上也有不少人遇到一样的问题,但是能找到的数量有限的解决办法写得都不详细,很难让人理 ...
- PLSQL 创建自定义函数注意事项
2017-6-8周四,今天遇到的需求是,从数据库中查找出某张表的某些数据,并将这些数据做简单的加减运算再得到结果集,没有思路,后来问辉哥,给我的建议是给这些运算封装成一个SQL函数,select选择字 ...
- 如何卸载Centos自带jdk
1.搜索安装的jdk: rpm -qa|grep jdk 结果如下: java-1.7.0-openjdk-1.7.0.45-2.4.3.3.el6.x86_64 java-1.6.0-openjdk ...
- Find、FindAll、Where的区别
Find.FindAll是一个List<T>的方法,返回一个new List<T>包括符合条件的数据 Where是一个linq方法,适用于任意继承了IEnumerable接口的 ...
- async/await 的基本实现和 .NET Core 2.1 中相关性能提升
前言 这篇文章的开头,笔者想多说两句,不过也是为了以后再也不多嘴这样的话. 在日常工作中,笔者接触得最多的开发工作仍然是在 .NET Core 平台上,当然因为团队领导的开放性和团队风格的多样性(这和 ...
- Google Bigtable (中文版)
http://dblab.xmu.edu.cn/post/google-bigtable/ Abstract BigTable是一个分布式存储系统,它可以支持扩展到很大尺寸的数据:PB级别的数据,包含 ...
- JSF基础
JSF基础 1)JSF(JavaServer Faces)一种基于Java的Web应用的用户界面软件框架. 旨在降低web应用开发难度.减轻开发人员编写和维护web应用的负担. 一个基于JSF框架构建 ...
- Redis的安装及学习
最近因为做Chatbot项目需要对于NoSQL数据库进行研究,调研范围包括MongoDB和Redis.本文将介绍Redis在Windows环境的安装及如何利用python来操作Redis数据库. Re ...
- php数据导出excel
/** * 导出数据为excel表格 *@param $data 一个二维数组,结构如同从数据库查出来的数组 *@param $title excel的第一行标题,一个数组,如果为空则没有标题 *@p ...
- Proxy SwitchyOmega配合Shawdowsocks使用的配置
国内环境如果想使用Shawdowsocks来FQ,几乎一定会装ProxyOmega来进行配合使用,简单讲讲ProxyOmega如何和Shawdowsocks进行协同. 准备 Google chrome ...