ZJOI 2015 幻想乡战略游戏(动态点分治)
题意
思路
首先要明确一点,答案分布是有单调性的。什么意思呢?假设我们的答案在 \(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 幻想乡战略游戏(动态点分治)的更多相关文章
- [ZJOI2015]幻想乡战略游戏——动态点分治
[ZJOI2015]幻想乡战略游戏 带修改下,边点都带权的重心 随着变动的过程中,一些子树内的点经过会经过一些公共边.考虑能不能对这样的子树一起统计. 把树上贡献分块. 考虑点分治算法 不妨先把题目简 ...
- 【BZOJ3924】[Zjoi2015]幻想乡战略游戏 动态树分治
[BZOJ3924][Zjoi2015]幻想乡战略游戏 Description 傲娇少女幽香正在玩一个非常有趣的战略类游戏,本来这个游戏的地图其实还不算太大,幽香还能管得过来,但是不知道为什么现在的网 ...
- 解题:ZJOI 2015 幻想乡战略游戏
题面 神**所有点都爆int,我还以为我写出什么大锅了,不开long long见祖宗... 动态点分治利用点分树树高不超过log的性质,我们对每个点维护一个子树和,一个点分树子树和,一个点分树上父亲的 ...
- [BZOJ3924][ZJOI2015]幻想乡战略游戏(动态点分治)
题目描述 傲娇少女幽香正在玩一个非常有趣的战略类游戏,本来这个游戏的地图其实还不算太大,幽香还能管得过来,但是不知道为什么现在的网游厂商把游戏的地图越做越大,以至于幽香一眼根本看不过来,更别说和别人打 ...
- P3345 [ZJOI2015]幻想乡战略游戏 动态点分治
\(\color{#0066ff}{ 题目描述 }\) 傲娇少女幽香正在玩一个非常有趣的战略类游戏,本来这个游戏的地图其实还不算太大,幽香还能管得过来,但是不知道为什么现在的网游厂商把游戏的地图越做越 ...
- 【bzoj3924】[Zjoi2015]幻想乡战略游戏 动态点分治
题目描述 傲娇少女幽香正在玩一个非常有趣的战略类游戏,本来这个游戏的地图其实还不算太大,幽香还能管得过来,但是不知道为什么现在的网游厂商把游戏的地图越做越大,以至于幽香一眼根本看不过来,更别说和别人打 ...
- ZJOI2015 幻想乡战略游戏 动态点分治_树链剖分_未调完
Description 傲娇少女幽香正在玩一个非常有趣的战略类游戏,本来这个游戏的地图其实还不算太大,幽香还能管得过来,但是不知道为什么现在的网游厂商把游戏的地图越做越大,以至于幽香一眼根本看不过来, ...
- BZOJ 3924: [Zjoi2015]幻想乡战略游戏(动态点分治)
这种动态点分治嘛,GDKOI时听打到了,也有同学讲到了,所以印象比较深刻也就想出来了,然后就在实现方面卡了好久= = 不得不说CLJ说得真的太简单了,实现方面根本没提. 首先我们可以先用树分治构建出这 ...
- [ZJOI2015][bzoj3924] 幻想乡战略游戏 [动态点分治]
唉:-(动态点分治的思想真是复杂...... 先码住,再做几道题再来填坑 PS:接下来的Code因为用了倍增lca所以TLE一部分,但是懒得改成RMQ了...... Code: #include< ...
- loj 2135 「ZJOI2015」幻想乡战略游戏 - 动态点分治
题目传送门 传送门 题目大意 给定一棵树,初始点权都为0,要求支持: 修改点权 询问带权重心 询问带权重心就在点分树上跑一下就行了.(枚举跳哪个子树更优) 剩下都是基础点分治. 学了一下11-dime ...
随机推荐
- 使用js实现登录随机验证码的效果
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...
- 《nodejs开发指南》微博实例express4.x版
之前一直执着于前端开发,最近几天,开始学起了nodejs.作为一名前端开发者,见到这样一门用javascript写的后台自然是很激动的.但是,后台毕竟不同于前端,在学习的过程中,还是会遇到不少问题. ...
- python中的logger模块
logger 提供了应用程序可以直接使用的接口handler将(logger创建的)日志记录发送到合适的目的输出filter提供了细度设备来决定输出哪条日志记录formatter决定日志记录的最终输出 ...
- web前端学习路线(含20个真实web开发项目集合)
目前web前端工程师日均岗位缺口已经超过50000,随着互联网+的深入发展,html5作为前端展示技术,市场人才需求量将呈直线上涨. Web前端工程师的岗位职责是利用HTML.CSS.Java.DOM ...
- 五一 DAY2
DAY 2 比如:依次输入 3 1 5 4 2 插入 6 这里FZdalao有一个很巧妙的构造,直接吧输入的数字排成一个二 ...
- Python爬虫——小说
#encoding:utf8 import re import urllib2 url = 'http://www.23us.com/html/55/55304/' request = urllib2 ...
- 每日linux命令学习-sed
Linux的文本处理实用工具主要由sed和awk命令,二者虽然略有差异,但都使用正则表达式,默认使用标准I/O,并且使用管道命令可以将前一个命令的输出作为下一个命令的输入.笔者将在本节学习sed命令. ...
- css技巧-案例
点击进入:http://herry.wuhairui.cn/cssSkill/main.html
- self asyncio
import asyncio from threading import Thread import time print('main start:',time.time()) async def d ...
- Golang闭包入门了解
概念闭包就是一个函数与其相关的引用环境组成的一个整体.闭包本质其实是一个函数,但是这个函数会用到函数外的变量,它们共同组成的整体我们叫做闭包. 简单举例说明 package main import ( ...