此题绝了,$O(n^{1.5}\ log\ n)$都可以过掉。。。。

题目大意:给你一颗$n$个点的树,每条边边权不是2就是$1$,有$m$个询问,每次询问一个人从$x$点走到$y$点,每天可以走的里程数不超过$k$,问你从$x$至$y$至少需几天。

数据范围:$n≤10^5$。

我们将询问分成$k≤\sqrt{n}$和k$>\sqrt{n}$两类。

对于$k>\sqrt{n}$的,每次跳跃我们直接大力倍增就可以了,不难发现此方法单次的时间复杂度为$O(\sqrt{n}log\  n)$。

对于$k≤\sqrt{n}$的,我们将$k$相同的分为一类,令$g[i][j]$表示从i往根走$2^j$天走到的位置,然后大力倍增就可以了,不难发现单次倍增找答案的时间复杂度是$O(log\ n)$的,重建一次倍增数组的时间复杂度是$O(n\ log\  n)$的,总时间复杂度为$O(n^{1.5}\ log n+m\ log n)$。

如此粗暴的做法居然能在$350ms$跑过去,真是绝了(敢写敢过。。。。)

 #include<bits/stdc++.h>
#define M 100005
#define N 17
using namespace std;
struct edge{int u,v,next;}e[M*]={}; int head[M]={},use=;
void add(int x,int y,int z){use++;e[use].u=y;e[use].v=z;e[use].next=head[x];head[x]=use;}
int f[M][N]={},dep[M]={},dis[M]={};
void dfs(int x,int fa,int hh){
f[x][]=fa; dep[x]=dep[fa]+; dis[x]=dis[fa]+hh;
for(int i=;i<N;i++) f[x][i]=f[f[x][i-]][i-];
for(int i=head[x];i;i=e[i].next) if(e[i].u!=fa) dfs(e[i].u,x,e[i].v);
}
int getlca(int x,int y){
if(dep[x]<dep[y]) swap(x,y); int cha=dep[x]-dep[y];
for(int i=N-;~i;i--) if((<<i)&cha) x=f[x][i];
for(int i=N-;~i;i--) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
if(x==y) return x; return f[x][];
}
int getdis(int x,int y){return dis[x]+dis[y]-*dis[getlca(x,y)];}
int _j=;
int jumpdn(int x,int y,int d){
int now=dis[y]-dis[x]; if(now<=d) return y;
for(int i=N-;~i;i--)
if(dis[f[y][i]]-dis[x]>=d)
y=f[y][i];
if(dis[y]-dis[x]>d) y=f[y][];
return y;
}
int jumpup(int x,int y,int d){
if(y){
int lca=getlca(x,y); _j=;
if(dis[x]-dis[lca]<=d){
d-=dis[x]-dis[lca]; _j=;
return jumpdn(lca,y,d);
}
}
for(int i=N-;~i;i--) if(dis[x]-dis[f[x][i]]<=d) d-=dis[x]-dis[f[x][i]],x=f[x][i];
return x;
}
int g[M][N]={},D=;
void dfs(int x,int fa){
g[x][]=jumpup(x,,D); for(int i=;i<N;i++) g[x][i]=g[g[x][i-]][i-];
for(int i=head[x];i;i=e[i].next) if(e[i].u!=fa) dfs(e[i].u,x);
}
int query(int &x,int lca){int res=;
for(int i=N-;~i;i--){
if(dis[x]-dis[lca]<D) return res;
if(dep[g[x][i]]>=dep[lca]) x=g[x][i],res+=<<i;
}
return res;
}
int n,m,sq;
struct ask{
int x,y,d,id; ask(){x=y=d=id=;}
void rd(int ID){id=ID; scanf("%d%d%d",&x,&y,&d);}
friend bool operator <(ask a,ask b){return a.d<b.d;}
int query1(){
if(x==y) return ;
int lca=getlca(x,y),res=; _j=;
while(_j==) x=jumpup(x,y,d),res++;
while(x!=y) x=jumpdn(x,y,d),res++;
return res;
}
int query2(){
int lca=getlca(x,y),res=;
if(D!=d){D=d;dfs(,);}
res+=query(x,lca);
res+=query(y,lca);
res+=(getdis(x,y)>D)+(getdis(x,y)>);
return res;
}
}p[M]; int ans[M]={};
int main(){
scanf("%d",&n); sq=(n<=?:);
for(int i=,x,y,z;i<n;i++) scanf("%d%d%d",&x,&y,&z),add(x,y,z),add(y,x,z);
dfs(,,); dis[]=-;
scanf("%d",&m);
for(int i=;i<=m;i++) p[i].rd(i);
sort(p+,p+m+);
for(int i=;i<=m;i++){
if(p[i].d<=sq) ans[p[i].id]=p[i].query2();
else ans[p[i].id]=p[i].query1();
}
for(int i=;i<=m;i++) printf("%d\n",ans[i]);
}

【CODECHEF】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 TRIPS Children Trips (分块、倍增)

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

  3. CODECHEF Oct. Challenge 2014 Children Trips

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

  4. 【codechef】Children Trips

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

  5. 题解 Children Trips

    题目传送门 Description 给出一个大小为 \(n\) 的边权全为 \(1,2\) 的带权树,有 \(q\) 此查询,每次给出 \(u,v,p\) ,问 \(u\to v\) 每次可以最多走边 ...

  6. CodeChef TRIPS-Children Trips 树上分块

    参考文献国家集训队2015论文<浅谈分块在一类在线问题的应用>-邹逍遥 题目链接 题目大意 一棵n个节点的树,树的每条边长度为1或2,每次询问x,y,z. 要求输出从x开始走,每次只能走到 ...

  7. Codechef April Challenge 2019 游记

    Codechef April Challenge 2019 游记 Subtree Removal 题目大意: 一棵\(n(n\le10^5)\)个结点的有根树,每个结点有一个权值\(w_i(|w_i\ ...

  8. 「Codechef April Lunchtime 2015」Palindromeness

    「Codechef April Lunchtime 2015」Palindromeness 解题思路 : 考虑对于回文子串 \(s\) 贡献的定义: \[ value_s = [\ s[1,\lflo ...

  9. 后缀数组的倍增算法(Prefix Doubling)

    后缀数组的倍增算法(Prefix Doubling) 文本内容除特殊注明外,均在知识共享署名-非商业性使用-相同方式共享 3.0协议下提供,附加条款亦可能应用. 最近在自学习BWT算法(Burrows ...

随机推荐

  1. URL编码转换函数:escape()、encodeURI()、encodeURIComponent()

          函数出现时间:                      escape()                                javascript 1.0           ...

  2. spring boot2.0冷知识

    首先,Spring Boot 2.0.0 要求 Java 8 或更高版本,不再支持 Java 6 和 7. 在 Spring Boot 2.0 中,许多配置属性已被重命名或被删除,相应地,开发者需要升 ...

  3. 【转】MapReduce:详解Shuffle过程

    ——转自:{http://langyu.iteye.com/blog/992916} Shuffle过程是MapReduce的核心,也被称为奇迹发生的地方.要想理解MapReduce, Shuffle ...

  4. flac3d自定义变量输出云图

    定义单元体能量为微单元体的应变比能,即当应力和应变满足线性关系时,微单元体在三向应力状态下的应变比能为: (3.1) 下面代码为用户自定义云图显示变量. Flac3d Code new gen zon ...

  5. (网络流 模板 Dinic) Drainage Ditches --POJ --1273

    链接: http://poj.org/problem?id=1273 代码: //Dinic #include<stdio.h> #include<string.h> #inc ...

  6. MDX示例:求解中位数、四分位数(median、quartile)

    一个人力资源咨询集团通过网络爬虫采集手段将多个知名招聘网站上发布的求职和招聘等信息准实时采集到自己的库里,形成一个数据量浩大的招聘信息库,跟踪全国招聘和求职的行业.工种.职位.待遇等信息,并通过商业智 ...

  7. Moving XML/BI Publisher Components Between Instances

    As it is well known fact that XMLPublisher stores the metadata and physical files for templates and ...

  8. C++虚函数表(vtbl)

    C++的虚函数的作用就是为了实现多态的机制,利用内存的指针偏移来实现将基类型的指针指向的内存空间用子类对象来初始化.这样经过内部虚表的运作,实现可以通过基类指针来调用子类所定义的方法. 这种技术,其实 ...

  9. Python学习-40.Python中的迭代

    在上一篇中,我们使用了生成器来创建了一个可遍历的对象.在其中,我们使用了yield关键字. Python我也正在学习中,因此对yield的本质我并不熟悉,但是,在C#中,yield关键字则是语法糖,其 ...

  10. 自适应XAML布局经验总结 (三) 局部布局设计模式2

    本系列对实际项目中的XAML布局场景进行总结,给出了较优化的自适应布局解决方案,希望对大家有所帮助. 下面继续介绍局部布局设计模式. 5. 工具箱模式 绘图,三维模型操作等需要工具的情况,可以使用带分 ...