题目传送门

Description

给出一个大小为 \(n\) 的边权全为 \(1,2\) 的带权树,有 \(q\) 此查询,每次给出 \(u,v,p\) ,问 \(u\to v\) 每次可以最多走边权和 \(\le p\) 的路径,问最少走多少次。

\(n,q\le 10^5\)

Solution

因为自己没有想出来,所以还是写一发题解。

首先边权比较有迷惑性,但是这个 \(\le 2\) 确实多少用。考虑根号分治,可以发现 \(p>\sqrt n\) 最多只会爬 \(\sqrt n\) 次,所以可以直接暴力爬,即倍增找到每次可以走到的下一个点。

考虑 \(\sqrt n\),发现我们仍可以使用倍增,即处理出一个点走 \(2^i\) 次会走到哪里。

复杂度 \(\Theta(n\sqrt n\log n)\) 。

Code

#include <bits/stdc++.h>
using namespace std; #define Int register int
#define MAXN 100005 template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');}
template <typename T> inline void chkmax (T &a,T b){a = max (a,b);}
template <typename T> inline void chkmin (T &a,T b){a = min (a,b);} int n,m,siz; struct edge{int v,w;};
vector <edge> g[MAXN]; struct str{
int u,v,P,ind;
bool operator < (const str &t)const{return P < t.P;}
}seq[MAXN]; int dep[MAXN],dis[MAXN],par[MAXN][21];
int getlca (int u,int v){
if (dep[u] < dep[v]) swap (u,v);
for (Int i = 20,dis = dep[u] - dep[v];~i;-- i) if (dis >> i & 1) u = par[u][i];
if (u == v) return u;
else{
for (Int i = 20;~i;-- i) if (par[u][i] ^ par[v][i]) u = par[u][i],v = par[v][i];
return par[u][0];
}
} void dfs (int u,int fa){
dep[u] = dep[fa] + 1,par[u][0] = fa;
for (Int i = 1;i <= 20;++ i) par[u][i] = par[par[u][i - 1]][i - 1];
for (edge to : g[u]){
int v = to.v,w = to.w;
if (v == fa) continue;
dis[v] = dis[u] + w,dfs (v,u);
}
} int getjump (int u,int p){
for (Int i = 20;~i;-- i) if (par[u][i] && dis[u] - dis[par[u][i]] <= p)
// cout << u << " -> " << par[u][i] << endl,
p -= dis[u] - dis[par[u][i]],u = par[u][i];
return u;
} struct node{int lft,stp;}; node getit1 (int u,int lca,int p){
int stp = 0;
while (u ^ lca){
int now = getjump (u,p);
if (dep[now] > dep[lca]) stp ++,u = now;
else break;
}
return node{dis[u] - dis[lca],stp};
} int st[MAXN][21];
void makeit (int P){
for (Int i = 1;i <= n;++ i) st[i][0] = getjump (i,P);
// cout << P << ": ------------ " << endl;
for (Int j = 1;(1 << j) <= n;++ j)
for (Int i = 1;i <= n;++ i)
st[i][j] = st[st[i][j - 1]][j - 1];
// cout << i << " jump " << (1 << j) << ": " << st[i][j] << endl;
} node getit2 (int u,int lca,int p){
int stp = 0;
for (Int i = 20;~i;-- i) if (st[u][i] && dep[st[u][i]] > dep[lca]) stp += (1 << i),u = st[u][i];
return node{dis[u] - dis[lca],stp};
} int solveit (int x,int y,int P){
if (x == y) return 0;
int lca = getlca (x,y);
node t1 = P <= siz ? getit2 (x,lca,P) : getit1 (x,lca,P);
node t2 = P <= siz ? getit2 (y,lca,P) : getit1 (y,lca,P);
int now = t1.stp + t2.stp;
if (t1.lft + t2.lft <= P) return now + 1;
else return now + 2;
} int ans[MAXN];
signed main(){
// freopen ("data.in","r",stdin);
// freopen ("f1.out","w",stdout);
read (n),siz = sqrt (n);
for (Int i = 2,u,v,w;i <= n;++ i) read (u,v,w),g[u].push_back (edge{v,w}),g[v].push_back (edge{u,w});
dfs (1,0),read (m);
for (Int i = 1;i <= m;++ i) read (seq[i].u,seq[i].v,seq[i].P),seq[i].ind = i;
sort (seq + 1,seq + m + 1);
for (Int i = 1;i <= m;++ i){
if (seq[i].P <= siz){
if (seq[i].P != seq[i - 1].P) makeit (seq[i].P);
ans[seq[i].ind] = solveit (seq[i].u,seq[i].v,seq[i].P);
}
else ans[seq[i].ind] = solveit (seq[i].u,seq[i].v,seq[i].P);
}
for (Int i = 1;i <= m;++ i) write (ans[i]),putchar ('\n');
return 0;
}

题解 Children Trips的更多相关文章

  1. [CC-TRIPS]Children Trips

    [CC-TRIPS]Children Trips 题目大意: \(n(n\le10^5)\)座城市构成一棵树,且树上的每条边的长度\(l_i\)满足\(1\le l_i\le 2\).\(m(m\le ...

  2. 【codechef】Children Trips

    Portal -->CC_Children Trips Solution (英文题解看得真爽qwq不过写的好详细啊ovo) 首先这题有一个很重要的条件就是边权是\(1\)或者\(2\),所以虽然 ...

  3. CODECHEF Oct. Challenge 2014 Children Trips

    @(XSY)[分塊, 倍增] Description There's a new trend among Bytelandian schools. The "Byteland Tourist ...

  4. Codechef TRIPS Children Trips (分块、倍增)

    题目链接: https://www.codechef.com/problems/TRIPS 感觉CC有点毒瘤啊.. 题解: 首先有一个性质可能是因为太傻所以网上没人解释,然而我看了半天: 就是正序和倒 ...

  5. 【CODECHEF】Children Trips 倍增

    此题绝了,$O(n^{1.5}\ log\ n)$都可以过掉.... 题目大意:给你一颗$n$个点的树,每条边边权不是2就是$1$,有$m$个询问,每次询问一个人从$x$点走到$y$点,每天可以走的里 ...

  6. HDU1297 Children’s Queue (高精度+递推)

    Children’s Queue Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  7. 《ACM国际大学生程序设计竞赛题解Ⅰ》——基础编程题

    这个专栏开始介绍一些<ACM国际大学生程序设计竞赛题解>上的竞赛题目,读者可以配合zju/poj/uva的在线测评系统提交代码(今天zoj貌似崩了). 其实看书名也能看出来这本书的思路,就 ...

  8. To Miss Our Children Time(dp)

    To Miss Our Children Time Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65768/65768 K (Jav ...

  9. CF1037E. Trips

    题目链接 CF1037E. Trips 题解 每次删点后,对不满足要求的点拓扑 代码 #include<map> #include<queue> #include<vec ...

随机推荐

  1. Go测试--main测试

    目录 简介 示例 简介 子测试的一个方便之处在于可以让多个测试共享Setup和Tear-down.但这种程度的共享有时并不满足需求,有时希望在整个测试程序做一些全局的setup和Tear-down,这 ...

  2. 集合框架2- ArrayList

    其实 Java 集合框架也叫做容器,主要由两大接口派生而来,一个是 collection,主要存放对象的集合.另外一个是Map, 存储着键值对(两个对象)的映射表. 下面就来说说 List接口,Lis ...

  3. 1,Spark参数调优

    Spark调优 目录 Spark调优 一.代码规范 1.1 避免创建重复RDD 1.2 尽量复用同一个RDD 1.3 多次使用的RDD要持久化 1.4 使用高性能算子 1.5 好习惯 二.参数调优 资 ...

  4. NOIP模拟13「工业题·卡常题·玄学题」

    T1:工业题 基本思路   这题有一个重要的小转化: 我们将原来的函数看作一个矩阵,\(f(i,j-1)*a\)相当于从\(j-1\)向右走一步并贡献a,\(f(i-1,j)*b\)相当于从\(i-1 ...

  5. Devexpress TreeList控件使用

    增加显示列treeList1.Columns.Add(new TreeListColumn {Caption = "城市", FieldName = "Name" ...

  6. vue父组件中调用子组件的方法

    Vue项目中如何在父组件中直接调用子组件的方法: 方案一:通过ref直接调用子组件的方法: //父组件中 <template> <div> <Button @click= ...

  7. 【第十四篇】- Maven 自动化构建之Spring Cloud直播商城 b2b2c电子商务技术总结

    Maven 自动化构建 自动化构建定义了这样一种场景: 在一个项目成功构建完成后,其相关的依赖工程即开始构建,这样可以保证其依赖项目的稳定. 比如一个团队正在开发一个项目 bus-core-api, ...

  8. Dart简易教程 (1)---数据类型 运算符,类转换换

    从下面开始学习DART编程 以下是一个简单的示例: main(){ var number = 42; print(number);}程序说明,dart是一个强大的脚本类语言,可以不预先定义变量类型 , ...

  9. windows下配置VSCode免密SSH连接Linux机器

    先决条件 Windows下安装openssh软件(win10自带,可以不用搞) 从官网下载最新版本默认安装即可 VSCode安装插件 VSCode官方市场获取两个插件:"Remote - S ...

  10. Elasticsearch(ES)分词器的那些事儿

    1. 概述 分词器是Elasticsearch中很重要的一个组件,用来将一段文本分析成一个一个的词,Elasticsearch再根据这些词去做倒排索引. 今天我们就来聊聊分词器的相关知识. 2. 内置 ...