题意

https://loj.ac/problem/2135

思路

首先要明确一点,答案分布是有单调性的。什么意思呢?假设我们的答案在 \(u\) 节点,\((u,v)\) 之间有一条边且 \(u\) 离答案所在的点更近,那么 \(u\) 节点作为答案一定不比在 \(v\) 节点作答案劣。从链的角度分析在拓展到树上会比较好理解这个性质。

那么如果树是一棵完全二叉树,就可以 \(\log n\) 的回答了。从根节点向下跳,每次如果找到一个 \(\displaystyle2*sum[u]\geq tot\) (\(sum[u]\) 为 \(u\) 子树点权之和, \(tot\) 为整张图点权之和)的节点,就说明存在一个更优或不劣的答案,就往这个方向跳,直到不能跳为止。更新时直接暴力修改父亲,没什么可说的。

虽然这棵树不一定是完全二叉树,但是这棵树的“分治树”高度一定是不超过 \(\log n\) 的(我个人不习惯使用“分治树”的概念,而将点分治理解为重心管辖区域这样的概念)。那么就对这棵树进行点分,存下每个数对应的每一层重心对应容器的标号,到它的距离,以及是容是斥。此题的每层重心的容器就是两个变量 \(Sum,sum\) ,其中 \(Sum\) 表示此重心管辖区域权值乘距离总和,\(sum\) 表示权值总和。那么对于 \(u\) 一层重心对应容器编号为 \(id\) ,距离 \(dis\) ,容斥系数为 \(s\) ,产生贡献即为 \(s(Sum[id]+dis\cdot sum[id])\) 。那么就能 \(O(\log n)\) 的询问取某个点的答案是多少了。

修改仍为暴力修改,没什么好说的。

关键在于回答询问,我们从整张图的重心 \(u​\) 开始跳,这个重心 \(u​\) 将树劈成了若干个连通块(题目有条件,最多 \(20​\) 个),对于其中一个连通块,我们设 \(v​\) 在这个连通块内且与 \(u​\) 有边。我们查询选 \(v​\) 的得到的答案,如果小于等于 \(u​\) 的答案,那么就要跳了。妙的是这里跳的是这个连通块的重心 \(w​\),这样就可以保证复杂度了。所以,在点分的时候就要顺便把每个层重心 \(u​\) 的下层重心 \(w​\) ,以及对应的 \(v​\) 存下来。复杂度 \(O(20 \cdot n\log ^2n)​\) ,还是挺飘的。

代码

#include<bits/stdc++.h>
#define FOR(i,x,y) for(int i=(x),i##END=(y);i<=i##END;++i)
#define DOR(i,x,y) for(int i=(x),i##END=(y);i>=i##END;--i)
using namespace std;
template<typename T,typename _T>inline bool chk_min(T &x,const _T y){return y<x?x=y,1:0;}
template<typename T,typename _T>inline bool chk_max(T &x,const _T y){return x<y?x=y,1:0;}
typedef long long ll;
const int N=1e5+5;
template<const int maxn,const int maxm>struct Linked_list
{
int head[maxn],to[maxm],nxt[maxm],cost[maxm],tot;
Linked_list(){clear();}
void clear(){memset(head,-1,sizeof(head));tot=0;}
void add(int u,int v,int w){to[++tot]=v,cost[tot]=w,nxt[tot]=head[u],head[u]=tot;}
#define EOR(i,G,u) for(int i=G.head[u];~i;i=G.nxt[i])
};
Linked_list<N,N<<1>G,H;
ll sum[N*2],Sum[N*2];int Sc;
int lv[N],Sid[N][40];ll dis[N][40];bool sgn[N][40];
int sz[N];bool mark[N];
int n,q; void CFS(int u,int f,int tot,int &C,int &Mi)
{
sz[u]=1;int res=0;
EOR(i,G,u)
{
int v=G.to[i];
if(v==f||mark[v])continue;
CFS(v,u,tot,C,Mi);
sz[u]+=sz[v];
res=max(res,sz[v]);
}
res=max(res,tot-sz[u]);
if(chk_min(Mi,res))C=u;
}
void dfs_init(int u,int f,ll D,bool s)
{
Sid[u][++lv[u]]=Sc,dis[u][lv[u]]=D,sgn[u][lv[u]]=s;
EOR(i,G,u)
{
int v=G.to[i],w=G.cost[i];
if(v==f||mark[v])continue;
dfs_init(v,u,D+w,s);
}
}
void dac(int u,int f,int tot)
{
int rt=u,Mi=1e9;
CFS(u,0,tot,u,Mi);
if(f)H.add(f,u,rt);
mark[u]=1;
Sc++,dfs_init(u,0,0,1); EOR(i,G,u)
{
int v=G.to[i],w=G.cost[i];
if(mark[v])continue;
Sc++,dfs_init(v,u,w,0);
dac(v,u,sz[u]>sz[v]?sz[v]:tot-sz[u]);
}
}
void update(int u,int val)
{
FOR(i,1,lv[u])
{
int id=Sid[u][i];ll d=dis[u][i];
sum[id]+=val;
Sum[id]+=(ll)val*d;
}
}
ll query(int u)
{
ll res=0;
FOR(i,1,lv[u])
{
int id=Sid[u][i];ll d=dis[u][i];bool s=sgn[u][i];
if(s)res+=Sum[id]+d*sum[id];
else res-=Sum[id]+d*sum[id];
}
return res;
}
ll Query(int u)
{
ll res=query(u);
EOR(i,H,u)
{
int v=H.to[i],w=H.cost[i];
if(query(w)<=res)return Query(v);
}
return res;
} int main()
{
scanf("%d%d",&n,&q);
FOR(i,1,n-1)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
G.add(u,v,w),G.add(v,u,w);
}
int C,Mi=1e9;
CFS(1,0,n,C,Mi);
memset(mark,0,sizeof(mark));
memset(lv,0,sizeof(lv));
Sc=0;
dac(1,0,n);
while(q--)
{
int u,val;
scanf("%d%d",&u,&val);
update(u,val);
printf("%lld\n",Query(C));
}
return 0;
}

ZJOI 2015 幻想乡战略游戏(动态点分治)的更多相关文章

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

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

  2. 【BZOJ3924】[Zjoi2015]幻想乡战略游戏 动态树分治

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

  3. 解题:ZJOI 2015 幻想乡战略游戏

    题面 神**所有点都爆int,我还以为我写出什么大锅了,不开long long见祖宗... 动态点分治利用点分树树高不超过log的性质,我们对每个点维护一个子树和,一个点分树子树和,一个点分树上父亲的 ...

  4. [BZOJ3924][ZJOI2015]幻想乡战略游戏(动态点分治)

    题目描述 傲娇少女幽香正在玩一个非常有趣的战略类游戏,本来这个游戏的地图其实还不算太大,幽香还能管得过来,但是不知道为什么现在的网游厂商把游戏的地图越做越大,以至于幽香一眼根本看不过来,更别说和别人打 ...

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

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

  6. 【bzoj3924】[Zjoi2015]幻想乡战略游戏 动态点分治

    题目描述 傲娇少女幽香正在玩一个非常有趣的战略类游戏,本来这个游戏的地图其实还不算太大,幽香还能管得过来,但是不知道为什么现在的网游厂商把游戏的地图越做越大,以至于幽香一眼根本看不过来,更别说和别人打 ...

  7. ZJOI2015 幻想乡战略游戏 动态点分治_树链剖分_未调完

    Description 傲娇少女幽香正在玩一个非常有趣的战略类游戏,本来这个游戏的地图其实还不算太大,幽香还能管得过来,但是不知道为什么现在的网游厂商把游戏的地图越做越大,以至于幽香一眼根本看不过来, ...

  8. BZOJ 3924: [Zjoi2015]幻想乡战略游戏(动态点分治)

    这种动态点分治嘛,GDKOI时听打到了,也有同学讲到了,所以印象比较深刻也就想出来了,然后就在实现方面卡了好久= = 不得不说CLJ说得真的太简单了,实现方面根本没提. 首先我们可以先用树分治构建出这 ...

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

    唉:-(动态点分治的思想真是复杂...... 先码住,再做几道题再来填坑 PS:接下来的Code因为用了倍增lca所以TLE一部分,但是懒得改成RMQ了...... Code: #include< ...

  10. loj 2135 「ZJOI2015」幻想乡战略游戏 - 动态点分治

    题目传送门 传送门 题目大意 给定一棵树,初始点权都为0,要求支持: 修改点权 询问带权重心 询问带权重心就在点分树上跑一下就行了.(枚举跳哪个子树更优) 剩下都是基础点分治. 学了一下11-dime ...

随机推荐

  1. 微信小程序项目

    大体思想 微信小程序,没有DOM和BOM概念,所以,不会涉及到操作节点.它的主要思想是操作数据,然后改变视图层,即MVVM,如果知道angularJS,能很快的理解上手小程序.   一些开发小程序时, ...

  2. 富文本编辑器kindeditor插件

    官网:http://kindeditor.net/doc.php 步骤

  3. vue中使用第三方UI库的移动端rem适配方案

    需求:使用vue-cli脚手架搭建项目,并且使用第三方的UI库(比如vant,mint ui)的时候,因为第三方库用的都是用px单位,无法使用rem适配不同设备的屏幕. 解决办法:使用px2rem-l ...

  4. Redis性能监控

    参考地址: redis教程:http://www.runoob.com/redis/redis-tutorial.html redis百度百科:https://baike.baidu.com/item ...

  5. linux监控性能和网络的命令

    vmstat查看机器实时的综合情况:load,内存,swap,cpu使用率等方面 procs: r:运行队列中进程数量 b:等待IO的进程数量 memory(内存): swpd:使用虚拟内存大小 fr ...

  6. 20165316 实验一 Java开发环境的熟悉

    实验一 Java开发环境的熟悉 基础-Java环境的构建和简单程序 实验要求 建立"自己学号exp1"的目录 在"自己学号exp1"目录下建立src,bin等目 ...

  7. flask框架----设置配置文件的几种方式

    设置配置文件的几种方式 ==========方式一:============ app.config['SESSION_COOKIE_NAME'] = 'session_lvning' #这种方式要把所 ...

  8. kivy 滑动

    from kivy.uix.gridlayout import GridLayout from kivy.app import App from kivy.lang.builder import Bu ...

  9. django模板继承

    可以将每个html公共的部分做成一个基本模板,其他模板继承这个基本模板,则会拥有基本模板的所有内容. views.py from django.shortcuts import render def ...

  10. DevExpress 数据绑定