BZOJ 5129: [Lydsy1712月赛]树上传送 点分树+Dijkstra
Description
http://www.lydsy.com/JudgeOnline/upload/201712/prob12.pdf
Input
Output
暑假集训的时候点分树做的比较少,所以做这道题比较吃力,然而现在看这道题就比较简单了.
考虑直接建立点分树,每一个节点只需维护点分子树中 $BFS$ 序.
这样的好处是子树中点的深度是连续的,所以每次能到达的点肯定是连续的区间.
那么,只需按照 $Dijkstra$ 的运行过程,将点加入到优先队列中,并扩展队首.
每次扩展只需边删掉 $BFS$ 序中可以到达的点并加入到堆中,然后一边跳点分树中父亲即可.
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=300005;
namespace IO {
void setIO(string s) {
string in=s+".in";
string out=s+".out";
freopen(in.c_str(),"r",stdin);
freopen(out.c_str(),"w",stdout);
}
char *p1,*p2,buf[100000];
#define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
int rd() {
int x=0;
char c=nc();
while(c<48) c=nc();
while(c>47) x=(((x<<2)+x)<<1)+(c^48),c=nc();
return x;
}
};
namespace tree{
int edges;
int hd[maxn],to[maxn<<1],nex[maxn<<1];
int fa[maxn],top[maxn],siz[maxn],son[maxn],dep[maxn];
void addedge(int u,int v) {
nex[++edges]=hd[u],hd[u]=edges,to[edges]=v;
}
void dfs1(int u,int ff) {
dep[u]=dep[ff]+1,fa[u]=ff,siz[u]=1;
for(int i=hd[u];i;i=nex[i]) {
int v=to[i];
if(v==ff) continue;
dfs1(v,u), siz[u]+=siz[v];
if(siz[v]>siz[son[u]]) son[u]=v;
}
}
void dfs2(int u,int tp) {
top[u]=tp;
if(son[u]) dfs2(son[u],tp);
for(int i=hd[u];i;i=nex[i]) {
int v=to[i];
if(v==fa[u]||v==son[u])continue;
dfs2(v,v);
}
}
int LCA(int x,int y) {
while(top[x]^top[y]) {
dep[top[x]]>dep[top[y]]?x=fa[top[x]]:y=fa[top[y]];
}
return dep[x]<dep[y]?x:y;
}
int Dis(int x,int y) {
return dep[x]+dep[y]-(dep[LCA(x,y)]*2);
}
};
namespace Divide {
struct Node {
int dis,u;
Node(int dis=0,int u=0):dis(dis),u(u){}
}st[maxn],val[maxn*30];
queue<Node>q;
int mn,root,tp,edges;
int siz[maxn],mx[maxn],mark[maxn],Fa[maxn],in[maxn],hd[maxn],to[maxn*30],nex[maxn*30];
void Add(int u,Node e) {
nex[++edges]=hd[u],hd[u]=edges,val[edges]=e;
}
void getroot(int u,int ff) {
mx[u]=0, siz[u]=1;
for(int i=tree::hd[u];i;i=tree::nex[i]) {
int v=tree::to[i];
if(v==ff||mark[v]) continue;
getroot(v,u), siz[u]+=siz[v];
mx[u]=max(mx[u],siz[v]);
}
mx[u]=max(mx[u], mn-siz[u]);
if(mx[u] < mx[root]) root=u;
}
void bfs(int u) {
tp=0;
q.push(Node(0,u));
in[u]=u;
while(!q.empty()) {
Node e=q.front(); q.pop();
st[++tp]=e;
int x=e.u;
for(int i=tree::hd[x];i;i=tree::nex[i]) {
int v=tree::to[i];
if(mark[v]||in[v]==u) continue;
in[v]=u;
q.push(Node(e.dis+1,v));
}
}
for(int i=tp;i>=1;--i) Add(u, st[i]);
}
void divide(int u) {
mark[u]=1;
bfs(u);
for(int i=tree::hd[u];i;i=tree::nex[i]) {
int v=tree::to[i];
if(mark[v]) continue;
root=0,mn=siz[v],getroot(v,u);
Fa[root]=u;
divide(root);
}
}
void pre(int n) {
mx[0]=1000000000,mn=n,root=0,getroot(1,0);
divide(root);
}
};
int n,S;
int L[maxn];
ll C[maxn];
namespace Dijkstra {
ll d[maxn];
int flag[maxn];
struct Node {
ll dis;
int u;
Node(ll dis=0,int u=0):dis(dis),u(u){}
bool operator<(Node b) const {
return dis>b.dis;
}
};
priority_queue<Node>q;
void del(int x,int limit,ll ge,int u) {
if(limit<0) return;
while(Divide::hd[x] && Divide::val[Divide::hd[x]].dis<=limit) {
int v=Divide::val[Divide::hd[x]].u;
Divide::hd[x]=Divide::nex[Divide::hd[x]];
if(flag[v]) continue;
d[v]=ge, flag[v]=1, q.push(Node(d[v] + C[v], v));
}
if(Divide::Fa[x]) del(Divide::Fa[x],L[u]-tree::Dis(u,Divide::Fa[x]),ge,u);
}
void solve() {
d[S]=0,flag[S]=1;
q.push(Node(C[S],S));
while(!q.empty()) {
Node e=q.top(); q.pop();
del(e.u, L[e.u], e.dis, e.u);
}
}
};
int main() {
using namespace IO;
// setIO("input");
n=rd(),S=rd();
for(int i=1;i<n;++i) {
int u=rd(),v=rd();
tree::addedge(u,v);
tree::addedge(v,u);
}
tree::dfs1(1,0);
tree::dfs2(1,1);
for(int i=1;i<=n;++i) L[i]=rd(), C[i]=(ll)rd();
Divide::pre(n);
Dijkstra::solve();
for(int i=1;i<=n;++i) printf("%lld\n",Dijkstra::d[i]);
return 0;
}
BZOJ 5129: [Lydsy1712月赛]树上传送 点分树+Dijkstra的更多相关文章
- bzoj 5125: [Lydsy1712月赛]小Q的书架
新学了一波 决策单调性 dp 套路.... 这种dp一般是长这样的 => f[i][j] = max/min { f[i-1][k] + cost(k+1,j)} ,其中cost函数满足四边形 ...
- bzoj 5123: [Lydsy1712月赛]线段树的匹配
设f[0/1][x]为区间[1,x]的根向下 不选(0)或者选(1) 的dp pair<最优值,方案数>. 可以很容易的发现总状态数就是log级别的,因为2*n 与 (2*n+1 或者 ...
- [BZOJ 5127][Lydsy1712月赛]数据校验
Description 题库链接 给你一个长度为 \(n\) 的序列.\(m\) 次询问,每次询问序列的一个区间 \([l,r]\).对于 \([l,r]\) 内的所有子区间,询问值域是否连续.若存在 ...
- BZOJ 4881: [Lydsy1705月赛]线段游戏 动态规划 + 线段树
Description quailty和tangjz正在玩一个关于线段的游戏.在平面上有n条线段,编号依次为1到n.其中第i条线段的两端点坐 标分别为(0,i)和(1,p_i),其中p_1,p_2,. ...
- BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 )
BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 ) 题意分析 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 ...
- BZOJ Lydsy5月月赛 ADG题解
题目链接 BZOJ5月月赛 题解 好弱啊QAQ只写出三题 A 判断多干个数乘积是否是某个数的倍数有很多方法,比较常用的是取模,但这里并不适用,因为模数不定 会发现数都比较小,所以我们可以考虑分解质因子 ...
- KMP + BZOJ 4974 [Lydsy1708月赛]字符串大师
KMP 重点:失配nxtnxtnxt数组 意义:nxt[i]nxt[i]nxt[i]表示在[0,i−1][0,i-1][0,i−1]内最长相同前后缀的长度 图示: 此时nxt[i]=jnxt[i]=j ...
- BZOJ 3924 / Luogu P3345 [ZJOI2015]幻想乡战略游戏 (动态点分治/点分树)
题意 树的结构不变,每个点有点权,每一条边有边权,有修改点权的操作,设xxx为树中一点.求∑idist(x,i)∗a[i]\sum_idist(x,i)*a[i]i∑dist(x,i)∗a[i]的最 ...
- 【BZOJ 3735】苹果树 树上莫队(树分块+离线莫队+鬼畜的压行)
2016-05-09 UPD:学习了新的DFS序列分块,然后发现这个东西是战术核导弹?反正比下面的树分块不知道要快到哪里去了 #include<cmath> #include<cst ...
随机推荐
- 【不错】MySQL 事务隔离级别
一.事务描述 1.事务的四个特性 ACID 1. A:原子性 = 一个事务或者都成功.或者都失败: 2. C:一致性 = 在整个事务的生命周期里面,查询到的数据是一致的: MVCC多版本并发控制:利用 ...
- :hover 鼠标同时触发两个元素变化
HTML代码: <li> <span>4</span> <a href="#">巨型一号丝瓜水320ML</a>< ...
- note.js使用express创建项目的步骤以及ip和端口配置
1.安装express npm install -g express 2.创建项目 express -e 项目名称 3.打开cmd进入项目目录安装依赖 npm install 4.打开配置文件./bi ...
- Nginx服务器优势是什么
nginx介绍.功能,优势 https://www.cnblogs.com/wcwnina/p/8728391.html#!comments Nginx负载均衡,session共享问题,几种解决方案 ...
- [转帖]Oracle 使用sqlnet.ora/trigger限制/允许某IP或IP段访问指定用户
Oracle 使用sqlnet.ora/trigger限制/允许某IP或IP段访问指定用户 原创 Oracle 作者:maohaiqing0304 时间:2016-05-03 17:05:46 17 ...
- 【烦人的字符集】linux字符集问题,中文乱码
[1]快速修改命令 [2]locale 查看现在服务器的字符 [root@Master ~]# localeLANG=en_US.UTF-8LC_CTYPE="zh_CN.UTF-8&quo ...
- C函数调用过程原理及函数栈帧分析(转)
在x86的计算机系统中,内存空间中的栈主要用于保存函数的参数,返回值,返回地址,本地变量等.一切的函数调用都要将不同的数据.地址压入或者弹出栈.因此,为了更好地理解函数的调用,我们需要先来看看栈是怎么 ...
- centos 7 无网络情况下,解决yum 安装依赖rpm包
方法一:在一台有网络的机器,用yum下载好所需程序,传到另外一台网络的机器上安装 yum install xtrabackup --downloadonly --downloaddir=/rpmpat ...
- linux-memcache安装及memcached memcache扩展
linux memcached安装yum -y install libevent libevent-deve yum list memcached yum -y install memcached m ...
- ETL工具Kettle使用以及与Java整合实现数据清洗
本文主要讲述kettle的使用和与Java整合,具体下载与安装请自行百度! kettle有两种脚本方式:转换和工作,工作中可以添加转换.以下以转换为例. 1.新建一个转换, 2.在工作中经常用到的是表 ...