【codechef】Children Trips
Solution
(英文题解看得真爽qwq不过写的好详细啊ovo)
首先这题有一个很重要的条件就是边权是\(1\)或者\(2\),所以虽然说我也不知道为什么这样就能突然想到了分块(是不是不知道怎么搞的时候就想分块啊qwq)
我们按照学生的体力值是否大于\(\sqrt n\)将所有的询问分成两类,第一类是\(P<=\sqrt n\)的,第二类是\(P>\sqrt n\)的
我们首先来看\(P>\sqrt n\)的这类
如果说不考虑时间的话,我们有一种非常暴力的做法就是先预处理\(pre[i][j]\)数组用来倍增求\(lca\),然后再预处理一个\(dis[x]\)表示\(x\)这个节点到根的距离,有了这两个东西之后我们可以实现一个\(single\_jump(x,P)\),其中\(x\)表示开始往上跳的节点,\(P\)表示的是学生的体力值,这个过程的作用是在\(O(logn)\)的时间内求出\(x\)这个节点在体力限制为\(P\)的情况下,最远能够往上走到哪一个节点,也就是找到一个深度最浅的\(y\)满足\(dis[x]-dis[y]<=P\),并统计这个过程需要多少步
然后对于每次询问\((x,y,P)\)我们先求出\(lca\),然后分别从\(x\)和\(y\)两个节点开始\(single\_jump\)直到\(lca\),当然两边都可能有剩下的一小段,最后处理一下就好了(要么一步走完要么两步走完)
这个是最暴力的一个想法,耗时的原因很简单,因为从\(x\)和\(y\)开始暴力\(single\_jump\),如果\(P\)很小那就很凉了,但是对于\(P>\sqrt n\)的情况下,最多跳的步数是\(\sqrt n\)级别的,所以总的复杂度就是\(O(\sqrt n logn)\),用来处理\(P>\sqrt n\)的情况问题不大ovo
接下来就是第一类\(P<=\sqrt n\)的情况了
显然我们要对”暴力\(single\_jump\)“这步进行优化,也就是要实现一次跳多步\(single\_jump\)
最套路的想法就是同样的我们可以预处理一个倍增数组\(up[i][j]\),表示从\(i\)开始往上进行\(1<<j\)次\(single\_jump\)最浅能跳到哪里,处理方法跟求\(lca\)的倍增数组类似,只要先\(O(nlogn)\)求出\(up[i][0]\)然后大力转移就好了,有了这个数组之后我们就可以直接用倍增的方式求要跳多少步可以跳到哪里了,其他部分保持不变
但是能预处理的前提是我们知道\(P\)是多少,现在的问题是每一个询问的\(P\)都是不同的
也就是说每一次我们都要先\(O(nlogn)\)预处理一遍,这样显然是会爆炸的
但是注意到,如果我们只用这个方法来处理\(P<=\sqrt n\)的情况,\(P\)的取值只有\(\sqrt n\)种,我们将第一类的所有询问按照\(P\)值从小到大排个序,那么最坏的预处理的总复杂度就是\(O(n^\frac{3}{2}logn)\),算一下好像有点爆炸然后我们来看一下时间是8sec那。。大概。。也许。。可以吧(实际上cc上面交了一发跑出来是。。4点多秒。。)
不过分块的事情是真的qwq不能信复杂度qwq毕竟是上界(比如某道回转寿司的题明明算出来炸得不行但是就是能过并且跑得飞快。。)
代码大概长这个样子
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=1e5+10,TOP=16;
struct xxx{
int y,nxt,dis;
}a[N*2];
struct Data{
int left_dis,step;
Data(){}
Data(int x,int y){left_dis=x; step=y;}
};
struct Rec{
int x,y,P,id;
Rec(){}
Rec(int x1,int y1,int P1,int id1){x=x1; y=y1; P=P1; id=id1;}
friend bool operator < (Rec x,Rec y){return x.P<y.P;}
}rec1[N],rec2[N];
int h[N],dep[N],dis[N],ans[N];
int pre[N][TOP+1],up[N][TOP+1];
int n,m,tot,rec1_cnt,rec2_cnt,sq,Cnt;
void add(int x,int y,int d){a[++tot].y=y; a[tot].nxt=h[x]; h[x]=tot; a[tot].dis=d;}
void dfs(int fa,int x,int d,int Dis){
dis[x]=Dis; dep[x]=d;
pre[x][0]=fa;
for (int i=1;i<=TOP;++i) pre[x][i]=pre[pre[x][i-1]][i-1];
int u;
for (int i=h[x];i!=-1;i=a[i].nxt){
u=a[i].y;
if (u==fa) continue;
dfs(x,u,d+1,Dis+a[i].dis);
}
}
int get_lca(int x,int y){
if (dep[x]<dep[y]) swap(x,y);
for (int i=TOP;i>=0;--i)
if (dep[pre[x][i]]>=dep[y]) x=pre[x][i];
if (x==y) return x;
for (int i=TOP;i>=0;--i)
if (pre[x][i]!=pre[y][i]) x=pre[x][i],y=pre[y][i];
return pre[x][0];
}
int single_jump(int x,int P){
int now=dis[x];
for (int i=TOP;i>=0;--i){
if (now-dis[pre[x][i]]>P) continue;
x=pre[x][i];
}
return x;
}
Data large_up(int x,int aim,int P){
int tmp,left_dis=0,step=0;
while (x!=aim){
tmp=single_jump(x,P);
if (dep[tmp]>dep[aim]){
++step;
x=tmp;
}
else{
left_dis=dis[x]-dis[aim];
break;
}
}
return Data(left_dis,step);
}
Data small_up(int x,int aim,int P){
int step=0;
for (int i=TOP;i>=0;--i){
if (dep[up[x][i]]>dep[aim])
step+=1<<i,x=up[x][i];
}
return Data(dis[x]-dis[aim],step);
}
void solve(int x,int y,int P,int id){
if (x==y){ans[id]=0;return;}
int lca=get_lca(x,y);
Data tmp1,tmp2;
tmp1=P<=sq?small_up(x,lca,P):large_up(x,lca,P);
tmp2=P<=sq?small_up(y,lca,P):large_up(y,lca,P);
ans[id]=tmp1.step+tmp2.step;
if (tmp1.left_dis+tmp2.left_dis<=P) ++ans[id];
else ans[id]+=2;
}
void small_prework(int P){
++Cnt;//for debug qwq
for (int i=1;i<=n;++i) up[i][0]=single_jump(i,P);
for (int j=1;j<=TOP;++j)
for (int i=1;i<=n;++i)
up[i][j]=up[up[i][j-1]][j-1];
}
void Large(Rec *rec,int n){
for (int i=1;i<=n;++i)
solve(rec[i].x,rec[i].y,rec[i].P,rec[i].id);
}
void Small(Rec *rec,int n){
sort(rec+1,rec+1+n);
for (int i=1;i<=n;++i){
if (i==1||rec[i].P!=rec[i-1].P)
small_prework(rec[i].P);
solve(rec[i].x,rec[i].y,rec[i].P,rec[i].id);
}
}
int main(){
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
#endif
int x,y,d;
scanf("%d",&n);
sq=sqrt(n);
memset(h,-1,sizeof(h));
tot=0;
for (int i=1;i<n;++i){
scanf("%d%d%d",&x,&y,&d);
add(x,y,d); add(y,x,d);
}
dfs(0,1,1,0);
scanf("%d",&m);
rec1_cnt=0; rec2_cnt=0;
for (int i=1;i<=m;++i){
scanf("%d%d%d",&x,&y,&d);
if (d<=sq)
rec1[++rec1_cnt]=Rec(x,y,d,i);
else
rec2[++rec2_cnt]=Rec(x,y,d,i);
}
Large(rec2,rec2_cnt);
Small(rec1,rec1_cnt);
for (int i=1;i<=m;++i) printf("%d\n",ans[i]);
}
【codechef】Children Trips的更多相关文章
- 【CODECHEF】Children Trips 倍增
此题绝了,$O(n^{1.5}\ log\ n)$都可以过掉.... 题目大意:给你一颗$n$个点的树,每条边边权不是2就是$1$,有$m$个询问,每次询问一个人从$x$点走到$y$点,每天可以走的里 ...
- 【CodeChef】Querying on a Grid(分治,最短路)
[CodeChef]Querying on a Grid(分治,最短路) 题面 Vjudge CodeChef 题解 考虑分治处理这个问题,每次取一个\(mid\),对于\(mid\)上的三个点构建最 ...
- 【CF605E】Intergalaxy Trips(贪心,动态规划)
[CF605E]Intergalaxy Trips(贪心,动态规划) 题面 Codeforces 洛谷 有\(n\)个点,每个时刻第\(i\)个点和第\(j\)个点之间有\(p_{ij}\)的概率存在 ...
- 【CodeChef】Palindromeness(回文树)
[CodeChef]Palindromeness(回文树) 题面 Vjudge CodeChef 中文版题面 题解 构建回文树,现在的问题就是要求出当前回文串节点的长度的一半的那个回文串所代表的节点 ...
- 【CodeChef】Find a special connected block - CONNECT(斯坦纳树)
[CodeChef]Find a special connected block - CONNECT(斯坦纳树) 题面 Vjudge 题解 还是一样的套路题,把每个数字映射到\([0,K)\)的整数, ...
- 【CODECHEF】【phollard rho + miller_rabin】The First Cube
All submissions for this problem are available. Read problems statements in Mandarin Chinese and Rus ...
- 【高精度递推】【HDU1297】Children’s Queue
Children's Queue Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) ...
- 【codechef】FN/Fibonacci Number
题意 给出 c 和 P ,求最小的非负整数 n 使得 \(Fib(n)=c(mod~ P)\) 其中 P 是质数且 模 10 等于一个完全平方数(也就是说 P 的末位是个完全平方数,那么只能是 1 或 ...
- 【CodeChef】Prime Distance On Tree
vjudge 给定一棵边长都是\(1\)的树,求有多少条路径长度为质数 树上路径自然是点分治去搞,但是发现要求是长度为质数,总不能对每一个质数都判断一遍吧 自然是不行的,这个东西显然是一个卷积,我们合 ...
随机推荐
- Spring学习(1):侵入式与非侵入式,轻量级与重量级
一. 引言 在阅读spring相关资料,都会提到Spring是非侵入式编程模型,轻量级框架,那么就有必要了解下这些概念. 二. 侵入式与非侵入式 非侵入式:使用一个新的技术不会或者基本不改变原有代码结 ...
- 利用Tensorflow进行自然语言处理(NLP)系列之二高级Word2Vec
本篇也同步笔者另一博客上(https://blog.csdn.net/qq_37608890/article/details/81530542) 一.概述 在上一篇中,我们介绍了Word2Vec即词向 ...
- 华为中兴借eBay出海 靠零售渠道撬动市场
在跨境电商领域,大多数中国商家依靠“中国制造”的优势和价格战策略打拼出一条血路,在海外市场占领了自己的一席 之地.不过,山寨货纷纷出海的同时,中国本土的品牌商们也开始了探索海外市场之旅.目前,华为.中 ...
- ES6的新特性(20)—— Module 的加载实现
Module 的加载实现 上一章介绍了模块的语法,本章介绍如何在浏览器和 Node 之中加载 ES6 模块,以及实际开发中经常遇到的一些问题(比如循环加载). 浏览器加载 传统方法 HTML 网页中, ...
- 多源最短路——Floyd算法
Floyd算法 问题的提出:已知一个有向网(或者无向网),对每一对定点vi!=vj,要求求出vi与vj之间的最短路径和最短路径的长度. 解决该问题有以下两种方法: (1)轮流以每一个定点为源点,重复执 ...
- 0917 词法分析程序(java版)
1.运行结果: 2.源代码: package 词法分析;import java.util.Scanner;public class fenxi {public static void main(Str ...
- KNN算法之图像处理二
1.看了诸多博客,初步得到结论是:KNN不适合做图像分类. 2.如果偏要用此方法进行图像分类,距离计算为:对应的每个像素代表的像素值进行绝对差值计算,最后求和.这就是“图像的距离”
- ios程序后台继续运行
1.图标右上角显示消息个数 if ([[UIDevice currentDevice].systemVersion doubleValue] >= 8.0) { UIUserNotificati ...
- sql数据库表容量
标题:SQL Server 的最大容量规范 数据库的文件大小,文件数量都有限制. 表的大小也有限制,如果表过大,查询效率就会下降,考虑对数据进行分割,对历史数据进行独立存储.
- 运维工程师如果将web服务http专变为https
1:生成私钥 2:生成证书签署请求 3:在提供CA签署的web网站上,提交生成的证书签署请求 4:下载已经签署的CA证书 5:将证书的信息保留在web服务器中,且应用到提供web服务的 ...