BZOJ 3924: [Zjoi2015]幻想乡战略游戏(动态点分治)
这种动态点分治嘛,GDKOI时听打到了,也有同学讲到了,所以印象比较深刻也就想出来了,然后就在实现方面卡了好久= =
不得不说CLJ说得真的太简单了,实现方面根本没提。
首先我们可以先用树分治构建出这棵树的分治树,也就是把这棵树的重心作为根节点然后子树为他的子树的重心这样递归下去,然后每个节点存的是其子树的信息。
对于每个节点我们保存这个子树的dv的总和已经把该节点作为点的答案值
这样对于修改能在log n的时间内解决
寻找答案的时候,我们可以发现,如果现在节点的子树dv和*2大于总节点,那么向那个方向过去一定比原方案好
我们先从根节点开始,若发现答案在某棵子树时,我们考虑如何使其儿子节点的答案转变为整个树的答案,可以发现把除这个子树外的所有节点可以缩成一个节点并连在这棵子树上,然后就可以一直这样做下去,找到操作之后再把这些撤销
因此还是得维护一些奇奇怪怪的东西,但打出来还是挺短的
Code:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
#define maxn 100100
typedef long long ll;
typedef pair<ll,ll> ii;
typedef pair<ll,ii> iii;
#define fi first
#define se second
#define pb push_back
struct edges{int to,next,dist;}edge[maxn*];
int l,next[maxn];
inline void addedge(int x,int y,int z) {
edge[++l]=(edges){y,next[x],z};next[x]=l;
edge[++l]=(edges){x,next[y],z};next[y]=l;
}
bool done[maxn];
int s[maxn],f[maxn],root,size;
void dfs(int u,int fa){
s[u]=;f[u]=;
int v=;
for (int i=next[u];i;i=edge[i].next) {
if (done[v=edge[i].to]||v==fa) continue;
dfs(v,u);
s[u]+=s[v];
f[u]=max(f[u],s[v]);
}
f[u]=max(f[u],size-s[u]);
if (f[u]<f[root]) root=u;
}
vector<ii> pre[maxn];
void getdist(int u,int fa,int tar,int dist) {
pre[u].pb(ii(tar,dist));
s[u]=;int v=;
for (int i=next[u];i;i=edge[i].next) {
if (done[v=edge[i].to]||v==fa) continue;
getdist(v,u,tar,dist+edge[i].dist);
s[u]+=s[v];
}
}
vector<iii> ch[maxn];
void work(int u){
done[u]=;
int v=;
pre[u].pb(ii(u,));
for (int i=next[u];i;i=edge[i].next) {
if (done[v=edge[i].to]) continue;
getdist(v,,u,edge[i].dist);
f[]=size=s[v];
dfs(v,root=);
ch[u].pb(iii(root,ii(v,edge[i].dist)));
work(root);
}
}
ll cnt[maxn],sum[maxn];
vector<ll> sumdist[maxn];
inline void update(int x,ll y,ll z){
for (int i=;i<pre[x].size();i++) {
int u=pre[x][i].fi;
cnt[u]+=y;sum[u]+=z+y*pre[x][i].se;
if (i!=pre[x].size()-) {
int j=;
for (;j<ch[u].size();j++)
if (ch[u][j].fi==pre[x][i+].fi) sumdist[u][j]+=z+y*pre[x][i].se;
}
}
}
int realroot;
vector<iii> record;
inline ll query(){
int x=realroot;
int mx=;
record.clear();
while (x){
mx=;
for (int i=;i<ch[x].size();i++)
if (cnt[ch[x][mx].fi]<cnt[ch[x][i].fi]) mx=i;
if (ch[x].size()==||cnt[ch[x][mx].fi]*<=cnt[x]) {
ll ans=sum[x];
for (int i=;i<record.size();i++)
update(record[i].fi,record[i].se.fi,record[i].se.se);
return ans;
}
int v=ch[x][mx].fi;
record.pb(iii(ch[x][mx].se.fi,ii(-(cnt[x]-cnt[v]),
-(sum[x]-sumdist[x][mx]+(cnt[x]-cnt[v])*ch[x][mx].se.se))));
update(ch[x][mx].se.fi,cnt[x]-cnt[v],
sum[x]-sumdist[x][mx]+(cnt[x]-cnt[v])*ch[x][mx].se.se);
x=v;
}
}
int main(){
int n,Q;
scanf("%d%d",&n,&Q);
for (int i=;i<n;i++) {
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
addedge(x,y,z);
}
f[]=size=n;
dfs(,root=);
realroot=root;
work(root);
for (int i=;i<=n;i++) sumdist[i]=vector<ll>(ch[i].size(),);
while (Q--) {
int x,y;
scanf("%d%d",&x,&y);
update(x,y,);
printf("%lld\n",query());
}
return ;
}
BZOJ 3924: [Zjoi2015]幻想乡战略游戏(动态点分治)的更多相关文章
- bzoj 3924 [Zjoi2015]幻想乡战略游戏——动态点分治(暴力移动找重心)
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3924 度数只有20,所以从一个点暴力枚举其出边,就能知道往哪个方向走. 知道方向之后直接走到 ...
- [ZJOI2015]幻想乡战略游戏——动态点分治
[ZJOI2015]幻想乡战略游戏 带修改下,边点都带权的重心 随着变动的过程中,一些子树内的点经过会经过一些公共边.考虑能不能对这样的子树一起统计. 把树上贡献分块. 考虑点分治算法 不妨先把题目简 ...
- 【BZOJ3924】[Zjoi2015]幻想乡战略游戏 动态树分治
[BZOJ3924][Zjoi2015]幻想乡战略游戏 Description 傲娇少女幽香正在玩一个非常有趣的战略类游戏,本来这个游戏的地图其实还不算太大,幽香还能管得过来,但是不知道为什么现在的网 ...
- [BZOJ3924][ZJOI2015]幻想乡战略游戏(动态点分治)
题目描述 傲娇少女幽香正在玩一个非常有趣的战略类游戏,本来这个游戏的地图其实还不算太大,幽香还能管得过来,但是不知道为什么现在的网游厂商把游戏的地图越做越大,以至于幽香一眼根本看不过来,更别说和别人打 ...
- P3345 [ZJOI2015]幻想乡战略游戏 动态点分治
\(\color{#0066ff}{ 题目描述 }\) 傲娇少女幽香正在玩一个非常有趣的战略类游戏,本来这个游戏的地图其实还不算太大,幽香还能管得过来,但是不知道为什么现在的网游厂商把游戏的地图越做越 ...
- 【bzoj3924】[Zjoi2015]幻想乡战略游戏 动态点分治
题目描述 傲娇少女幽香正在玩一个非常有趣的战略类游戏,本来这个游戏的地图其实还不算太大,幽香还能管得过来,但是不知道为什么现在的网游厂商把游戏的地图越做越大,以至于幽香一眼根本看不过来,更别说和别人打 ...
- ZJOI2015 幻想乡战略游戏 动态点分治_树链剖分_未调完
Description 傲娇少女幽香正在玩一个非常有趣的战略类游戏,本来这个游戏的地图其实还不算太大,幽香还能管得过来,但是不知道为什么现在的网游厂商把游戏的地图越做越大,以至于幽香一眼根本看不过来, ...
- BZOJ 3924 / Luogu P3345 [ZJOI2015]幻想乡战略游戏 (动态点分治/点分树)
题意 树的结构不变,每个点有点权,每一条边有边权,有修改点权的操作,设xxx为树中一点.求∑idist(x,i)∗a[i]\sum_idist(x,i)*a[i]i∑dist(x,i)∗a[i]的最 ...
- bzoj 3924: [Zjoi2015]幻想乡战略游戏
Description 傲娇少女幽香正在玩一个非常有趣的战略类游戏,本来这个游戏的地图其实还不算太大,幽香还能管得过来,但是不知道为什么现在的网游厂商把游戏的地图越做越大,以至于幽香一眼根本看不过来, ...
随机推荐
- 关于Android反编译
详情查看:http://blog.csdn.net/ordinaryjoe/article/details/8626010
- ModelDriven动作(转)
所谓ModelDriven ,意思是直接把实体类当成页面数据的收集对象.比如,有实体类User 如下: package cn.com.leadfar.struts2.actions; public c ...
- android dialog圆角显示及解决出现的黑色棱角.(友情提示)
http://blog.csdn.net/jj120522/article/details/7871289 最近在开发一个天气预报的app,看到一个比较不错友情提示,如下: ...
- ios framework 开发 之 实战二 ,成功
1. 新建工程.引入cocoapod略过不提 2. 更改cocoapod类名 这是因为,引用framework的工程中,也有一个同样的文件,及文件里同样的类. 这个文件不能删除,但是可以重命名. 3. ...
- 更改pandas dataframe 列的顺序
摘自 stackoverflow 这是我的df: Net Upper Lower Mid Zsore Answer option More than once a day 0% 0.22% -0.12 ...
- hdu 1005解题报告
这道题目n的取值范围很大,1 <= n <= 100,000,000.因此肯定是需要优化才能AC. 首先我考虑到时是有没有通项公式,研究了一下,没发现什么东西,突然看到两个1时就想到会不会 ...
- html bottom html submit按钮表单控件与CSS美化
一.html submit与bottom按钮基本语法结构 1.html submit按钮在input标签里设置type="submit"即可设置此表单控件为按钮. submit按钮 ...
- StackView的功能和用法
StackView也是AdapterViewAnimator的子类,它也用于显示Adapter提供的系列View.SackView将会以“堆叠(Stack)”方式来显示多个列表项. 为了控制Stack ...
- C# winform初学者实例
快递单打印通 下载地址: http://pan.baidu.com/s/1nue5ifn
- Linux中的zero-copy技术
本文是对参考文章重要部分的摘录,同时进行简单地总结. 零拷贝技术的相关背景知识 传统的 Linux 操作系统的标准 I/O 接口是基于数据拷贝操作的,即 I/O 操作会导致数据在操作系统内核地址空间的 ...