【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\)的树,求有多少条路径长度为质数 树上路径自然是点分治去搞,但是发现要求是长度为质数,总不能对每一个质数都判断一遍吧 自然是不行的,这个东西显然是一个卷积,我们合 ...
随机推荐
- halcon学习相关资料(转载)
https://blog.csdn.net/maweifei/article/details/78162581 论坛.培训 halcon学习网:http://www.ihalcon.com/ 鸟叔机器 ...
- New begin
Purpose 今天更换了id,希望重新沉淀. 晚上看到国外一个博客,落款有个中文: 敬惜字纸. 共勉.
- [笔记] centos6.6编译安装httpd2.4.10
系统安装包是CentOS-6.6-x86_64-minimal.iso 查看一下uname信息 [root@localhost ~]# uname -a Linux localhost.localdo ...
- 从无到有之webpack+vuerouter的简单例子以及各个属性解释
之前一直没玩过webpack和vue,近两周才看这玩意,本文纯属自己的实验+之前angular作战经验的理解一些入门文章 首先webpack关于vue以及各个包 module.exports = { ...
- 王者荣耀交流协会scrum立会20171111
1.立会照片 成员王超,高远博,冉华,王磊,王玉玲,任思佳,袁玥全部到齐. master:高远博 2.时间跨度: 2017年11月10日 18:00 - 18:33 ,总计33分钟. 3.地 点: 一 ...
- P4tutorial实战
Tutorial样例实战 GitHub仓库地址 参考博客 实验一:SIGCOMM_2015/Sourse_Routing 实验环境: OS:Ubuntu16.04 bmv2:behavioral-mo ...
- 软件图书,偏.net方向
深入理解计算机系统(原书第2版) 作者:Randal E.Bryant:1981年在麻省理工学院获计算机科学博士学位,现任美国卡内基·梅隆大学计算机学院院长 内容: 深入浅出地介绍了处理器.编译器.操 ...
- lintcode-488-快乐数
488-快乐数 写一个算法来判断一个数是不是"快乐数". 一个数是不是快乐是这么定义的:对于一个正整数,每一次将该数替换为他每个位置上的数字的平方和,然后重复这个过程直到这个数变为 ...
- 201621123037 《Java程序设计》第10周学习总结
作业10-异常 标签(空格分隔): Java 1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常相关内容. 2. 书面作业 本次PTA作业题集异常 1. 常用异常 结合题集题目7 ...
- LR监控apache服务器
开启mod_status模块功能,在LR的controller中找到apache资源图双击并右键添加度量,如下图: 添加apache服务器IP地址.选择系统平台.添加需要监控的计数器即可进行 ...