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的更多相关文章

  1. bzoj 5125: [Lydsy1712月赛]小Q的书架

    新学了一波 决策单调性 dp 套路.... 这种dp一般是长这样的 => f[i][j] = max/min  { f[i-1][k] + cost(k+1,j)} ,其中cost函数满足四边形 ...

  2. bzoj 5123: [Lydsy1712月赛]线段树的匹配

    设f[0/1][x]为区间[1,x]的根向下 不选(0)或者选(1)  的dp pair<最优值,方案数>. 可以很容易的发现总状态数就是log级别的,因为2*n 与 (2*n+1 或者 ...

  3. [BZOJ 5127][Lydsy1712月赛]数据校验

    Description 题库链接 给你一个长度为 \(n\) 的序列.\(m\) 次询问,每次询问序列的一个区间 \([l,r]\).对于 \([l,r]\) 内的所有子区间,询问值域是否连续.若存在 ...

  4. BZOJ 4881: [Lydsy1705月赛]线段游戏 动态规划 + 线段树

    Description quailty和tangjz正在玩一个关于线段的游戏.在平面上有n条线段,编号依次为1到n.其中第i条线段的两端点坐 标分别为(0,i)和(1,p_i),其中p_1,p_2,. ...

  5. BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 )

    BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 ) 题意分析 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 ...

  6. BZOJ Lydsy5月月赛 ADG题解

    题目链接 BZOJ5月月赛 题解 好弱啊QAQ只写出三题 A 判断多干个数乘积是否是某个数的倍数有很多方法,比较常用的是取模,但这里并不适用,因为模数不定 会发现数都比较小,所以我们可以考虑分解质因子 ...

  7. 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 ...

  8. BZOJ 3924 / Luogu P3345 [ZJOI2015]幻想乡战略游戏 (动态点分治/点分树)

    题意 树的结构不变,每个点有点权,每一条边有边权,有修改点权的操作,设xxx为树中一点.求∑idist(x,i)∗a[i]\sum_idist(x,i)*a[i]i∑​dist(x,i)∗a[i]的最 ...

  9. 【BZOJ 3735】苹果树 树上莫队(树分块+离线莫队+鬼畜的压行)

    2016-05-09 UPD:学习了新的DFS序列分块,然后发现这个东西是战术核导弹?反正比下面的树分块不知道要快到哪里去了 #include<cmath> #include<cst ...

随机推荐

  1. CSS3—— 2D转换 3D转换 过渡 动画

    2D转换 对元素进行移动.缩放.转动.拉长或拉伸 ————>  ————>   移动 顺时针旋转 扩大/缩小 倾斜 2D变换合并  3D转换 绕x轴 绕y轴 过渡 从一种样式逐渐改变为另一 ...

  2. 【MM系列】SAP 关于物料间的替代问题

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[MM系列]SAP 关于物料间的替代问题   前 ...

  3. 【Qt开发】QThread中的互斥、读写锁、信号量、条件变量

    在gemfield的<从pthread到QThread>一文中我们了解了线程的基本使用,但是有一大部分的内容当时说要放到这片文章里讨论,那就是线程的同步问题.关于这个问题,gemfield ...

  4. HTTPS测试

    1.首先理解HTTPS的含义,清楚http与HTTPS的区别 2.相对于http而言,https更加安全,因 3.使用数字证书使传输更安全,数字证书使用keytool工具生成 测试准备: 创建公钥和秘 ...

  5. MySQL-快速入门(14)MySQL性能优化

    1.MySQL性能优化包括查询速度优化.数据库结构优化.数据库服务器优化等. 优化的切入点:合理的结构设计.表结构.索引.查询语句. 2.show status查询数据库的性能参数 show stat ...

  6. vue组件命名和传值

    一.vue组件命名: 组件有好几种命名方式, 可以使用 component-vue (短横线分隔命名).componentVue  (驼峰式命名) 或ComponentVue  (单词首字母) 因为h ...

  7. uboot初识

    一. 什么是uboot 1.1. uboot的由来 1.1.1. uboot是SourceForge上的开源项目 1.1.2. uboot就是由一个人发起,然后由整个网络上所有感兴趣的人共同维护发展而 ...

  8. 创建MySQL数据库账号

    为本项目创建数据库用户(不再使用root账户) create user 账号 identified by '密码'; grant all on 数据库.* to '用户'@'%'; flush pri ...

  9. 1、Java语言概述与开发环境——Java程序运行机制

    Java语言是一种特殊的高级语言,它既有解释型语言的特性,也具有编译型语言的特征,因为Java要经过先编译后解释两个步骤. 一.高级语言的运行机制 计算机高级语言按程序的执行方式可以分为编译型和解释型 ...

  10. Python yield用法浅析(stackoverflow)

    这是stackoverflow上一个关于python中yield用法的帖子,这里翻译自投票最高的一个回答,原文链接 here 问题 Python中yield关键字的用途是什么?它有什么作用?例如,我试 ...