洛谷题目传送门

题目大意

就是给你一棵树,每个点都有点权,每次任意询问两点间路径上点权第k小的值(强制在线)。

思路分析

第k小。。。。。。又是主席树了。但这次变成树了,无法直接维护前缀和。

又是树上差分的小套路——每一个点到根的前缀和还是很好维护对吧。

询问\(u,v\)的时候,我们可以知道\(size[root,u]\)和\(size[root,v]\)的和。

但我们需要的只是一条路径,\(lca(u,v)\)以上的全不要,\(lca(u,v)\)也只要算一次。

于是用\(size[root,u]+size[root,v]-size[root,lca(u,v)]-size[root,father(lca(u,v))]\),也就是询问的时候四个点一起跳。

求LCA最方便的是倍增法(不会的百度一下),还有每个点对应的线段树从其父亲的线段树继承而来(根节点从\(0\)号空线段树继承而来),这两个操作我们在一次dfs建树时就可以一并处理完了。

话说我好久没打过倍增LCA了,老是写挂。。。。。。

闲话

另外,本蒟蒻听说倍增的二维数组把长度小的那一维度(即表示\(2^j\)的维度)开在前面会跑的快一些。

于是本蒟蒻亲自验证了一下,开在前面1112ms,开在后面992ms(没开O2,开了以后两个差不多)。。。。。。

这又是什么鬼?!

难道有评测机的不稳定因素?(洛谷一直很稳定啊!)

或者是有其他原因?欢迎各位大佬指教。

下面贴代码(开在前面):

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define R register int
#define G c=getchar()
#define in(Z) G;\
while(c<'-')G;\
Z=c&15;G;\
while(c>'-')Z*=10,Z+=c&15,G;
const int N=100009,M=4000009;
int P,he[N],ne[N<<1],to[N<<1],f[18][N],d[N],b[N];
int n,SZ,a[N],g[N],rt[N],lc[M],rc[M],s[M];
void build(R&u,R l,R r){//建初始空线段树
u=++P;
if(l!=r){
R m=(l+r)>>1;
build(lc[u],l,m);
build(rc[u],m+1,r);
}
}
inline void insert(R*u,R v,R k){//更新
R l=1,r=SZ,m;
while(l!=r){
s[*u=++P]=s[v]+1;
m=(l+r)>>1;
if(k<=m)r=m,rc[*u]=rc[v],u=&lc[*u],v=lc[v];
else l=m+1,lc[*u]=lc[v],u=&rc[*u],v=rc[v];
}
s[*u=++P]=s[v]+1;
}
inline int ask(R u,R v,R w,R x,R k){//询问,四个点一起搞
R l=1,r=SZ,m,q;
while(l!=r){
m=(l+r)>>1;
q=s[lc[u]]+s[lc[v]]-s[lc[w]]-s[lc[x]];
if(k<=q)r=m,u=lc[u],v=lc[v],w=lc[w],x=lc[x];
else l=m+1,u=rc[u],v=rc[v],w=rc[w],x=rc[x],k-=q;
}
return g[l];
}
void dfs(R u,R fa){//建好树,顺便预处理LCA
d[u]=d[fa]+1;
f[0][u]=fa;
for(R&i=b[u];f[i+1][u]=f[i][f[i][u]];++i);
insert(&rt[u],rt[fa],lower_bound(g+1,g+SZ+1,a[u])-g);
for(R i=he[u];i;i=ne[i])
if(to[i]!=fa)dfs(to[i],u);
}
inline int getlca(R u,R v){//查LCA
R i;
if(d[u]<d[v])i=u,u=v,v=i;
for(i=b[u];d[u]>d[v]&&i>=0;--i)
if(d[f[i][u]]>=d[v])u=f[i][u];
for(i=b[u];i>=0;--i)
if(f[i][u]!=f[i][v])u=f[i][u],v=f[i][v];
return u==v?u:f[0][u];//这里老是忘记判
}
int main(){
register char c;
R p=1,m,i,u,v,k,lca,lans=0;
in(n);in(m);
for(i=1;i<=n;++i){in(a[i]);}
memcpy(g,a,(n+1)<<2);//搞出来离散化
sort(g+1,g+n+1);
SZ=unique(g+1,g+n+1)-g-1;
build(rt[0],1,SZ);
for(i=1;i<n;++i)
{
in(u);in(v);
to[++p]=v;ne[p]=he[u];he[u]=p;
to[++p]=u;ne[p]=he[v];he[v]=p;//建边
}
dfs(1,0);
while(m--){
in(u);in(v);in(k);
lca=getlca(u^=lans,v);
printf("%d\n",lans=ask(rt[u],rt[v],rt[lca],rt[f[0][lca]],k));
}
return 0;
}

洛谷P2633 Count on a tree(主席树,倍增LCA,树上差分)的更多相关文章

  1. 洛谷P2633 Count on a tree(主席树上树)

    题目描述 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个询问的答案,初始为0,即第一个 ...

  2. 洛谷 P2633 Count on a tree 主席树

    在一棵树上,我们要求点 $(u,v)$ 之间路径的第$k$大数. 对于点 $i$  ,建立 $i$  到根节点的一棵前缀主席树. 简单容斥后不难得出结果为$sumv[u]+sumv[v]−sumv[l ...

  3. 洛谷P2633 Count on a tree 主席树

    传送门:主席树 解题报告: 传送门! umm这题我还麻油开始做 所以 先瞎扯一波我的想法,如果错了我就当反面教材解释这种典型错误,对了我就不管了QwQ 就直接dfs,在dfs的过程中建树 然后就直接查 ...

  4. 洛谷 P2633 Count on a tree

    P2633 Count on a tree 题目描述 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中last ...

  5. 【BZOJ-2588】Count on a tree 主席树 + 倍增

    2588: Spoj 10628. Count on a tree Time Limit: 12 Sec  Memory Limit: 128 MBSubmit: 3749  Solved: 873[ ...

  6. 洛谷P2633 Count on a tree(主席树,倍增LCA)

    洛谷题目传送门 题目大意 就是给你一棵树,每个点都有点权,每次任意询问两点间路径上点权第k小的值(强制在线). 思路分析 第k小......又是主席树了.但这次变成树了,无法直接维护前缀和. 又是树上 ...

  7. ☆ [洛谷P2633] Count on a tree 「树上主席树」

    题目类型:主席树+\(LCA\) 传送门:>Here< 题意:给出一棵树.每个节点有点权.问某一条路径上排名第\(K\)小的点权是多少 解题思路 类似区间第\(K\)小,但放在了树上. 考 ...

  8. 洛谷P2633 Count on a tree

    题目描述 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个询问的答案,初始为0,即第一个 ...

  9. 洛谷 P2633 Count on a tree 题解

    题面 对于每个点建立一颗主席树: 然后按照树上差分的思想统计主席树的前缀和: lca+主席树+前向星存表就可以了: #include <bits/stdc++.h> #define inc ...

随机推荐

  1. java的myeclipse,java页面改动默认的javadoc方法

    在项目中右键点击新建class文件,在弹出的框中选择"here" 勾上enable project specific settings 选择comments中的types然后点击e ...

  2. 20155204《网络对抗》Exp7 网络欺诈防范

    20155204<网络对抗>Exp7 网络欺诈防范 一.基础问题回答 1.通常在什么场景下容易受到DNS spoof攻击 在不安全的网络环境下访问网站. 2.在日常生活工作中如何防范以上两 ...

  3. EAS_BI(扩展报表)

    case when 的使用 1. 扩展报表,一张收费单据中,下面分为分录 问题描述: 收费单中有一个分录用于记录检测的项目名称以及标准费用.收费单有自己的主键,分录中的外键即是收费单的主键,然后分录表 ...

  4. SSISDB4:当前正在运行的Package及其Executable

    SSISDB 系列随笔汇总: SSISDB1:使用SSISDB管理Package SSISDB2:SSIS工程的操作实例 SSISDB3:Package的执行实例 SSISDB4:当前正在运行的Pac ...

  5. effective c++ 笔记 (23-25)

    //---------------------------15/04/08---------------------------- //#23   宁以non_member.non_friend替换m ...

  6. 《Effective Java》学习笔记 —— 通用程序设计

    本章主要讨论局部变量.控制结构.类库.反射.本地方法的用法及代码优化和命名惯例. 第45条 将局部变量的作用域最小化 * 在第一次使用的它的地方声明局部变量(就近原则). * 几乎每个局部变量的声明都 ...

  7. DMS专线联通外网测试

    配置 CE Ping PE: “本地链接”-->属性-->"Internet 协议版本4(TCP/IPv4)",选择“使用下面的IP”,填写“172.16.10.21” ...

  8. C# 导入(读取) WPS ET文件

    本文章介绍基于VS2010 Winform 的WPS2016二次开发 ET数据读取程序 本程序支持多个Sheet页面 前提:引用WPS安装目录下的etapi.dll private void butt ...

  9. 20172308 实验五《Java面向对象程序设计 》实验报告

    20172308 2017-2018-2 实验五 <网络编程与安全>报告 课程:<程序设计与数据结构> 班级: 1723 姓名: 周亚杰 学号:20172308 实验教师:王志 ...

  10. 转发npm发布包的过程

    老板,来个npm账号! 因为你的包是要放在npm上的,所以,没有npm的账号,根本什么活都干不了. 在npm上注册一个账号是很简单的,随便填一下用户名密码邮箱,然后人家就会发个邮件给你,然后就注册成功 ...