我们可以思考怎么做呢。

首先我们需要进行一些分类讨论:

我们先思考一下如果所有关键点都在 \(p\) 的子树内,

那显然是所有关键点的 \(Lca\) 到 \(p\) 距离。

如果所有关键点一些在 \(p\) 的子树里,一些在子树外,则答案显然为 \(0\)。

那我们只需要接着讨论一下所有关键点在都在子树外的情况即可。

我们知道一个点一定会沿着祖先往下走,然后在往一个子树进入。

如果关键点全都是在祖先的一个子树内,那答案一定是这些关键点的 \(Lca\) 和 \(p\) 的距离。

否则这个答案一定是到祖先的链上的某个点,这个点满足是这个子树里有关键点且是最深的点。

区间 \(Lca\) 可以使用线段树解决,然后我们在 \(dfn\) 序上做一个主席树的操作,然后就可以查询子树内的点的情况了。

// code by fhq_treap
#include<bits/stdc++.h>
#define ll int
#define N 300005 inline ll read(){
char C=getchar();
ll A=0 , F=1;
while(('0' > C || C > '9') && (C != '-')) C=getchar();
if(C == '-') F=-1 , C=getchar();
while('0' <= C && C <= '9') A=(A << 1)+(A << 3)+(C - 48) , C=getchar();
return A*F;
} template <typename T>
void write(T x)
{
if(x < 0) {
putchar('-');
x = -x;
}
if(x > 9)
write(x/10);
putchar(x % 10 + '0');
return;
} ll n,q;
ll head[N],cnt;
struct P{
int to,next,w;
}e[N << 1];
inline void add(int x,int y,int w){
e[++cnt].to = y,e[cnt].next = head[x],e[cnt].w = w,head[x] = cnt;
} //tree ll dfn[N],s[N],inv[N];
ll dfncnt;
int fa[N][30],dep[N],end[N];
inline void dfs(int x,int f){
end[x] = dfn[x] = ++dfncnt;
dep[x] = dep[f] + 1;
inv[dfncnt] = x;
fa[x][0] = f;
for(int i = 1;i < 30;i ++)
fa[x][i] = fa[fa[x][i - 1]][i - 1];
for(int i = head[x];i;i = e[i].next){
int v = e[i].to;
if(v == f)continue;
s[v] = s[x] + e[i].w;
dfs(v,x);
end[x] = std::max(end[x],end[v]);
}
} inline ll lca(ll x,ll y){
if(dep[y] > dep[x])
std::swap(x,y);
for(int i = 29;i >= 0;--i){
if(dep[fa[x][i]] >= dep[y])
x = fa[x][i];
}
if(x == y)
return x;
for(int i = 29;i >= 0;--i){
if(fa[x][i] != fa[y][i])
x = fa[x][i],y = fa[y][i];
}
return fa[x][0];
} ll T[N << 2]; #define ls(x) (x << 1)
#define rs(x) (x << 1 | 1)
#define mid ((l + r) >> 1)
#define root 1,1,n inline void build(int u,int l,int r){
if(l == r){
T[u] = l;·1全额日图与i哦怕【-】
return ;
}
build(ls(u),l,mid);
build(rs(u),mid + 1,r);
T[u] = lca(T[ls(u)],T[rs(u)]);
return ;
} inline ll qlca(int u,int l,int r,int tl,int tr){
if(tl <= l && r <= tr)
return T[u];
ll li,ri;li = ri = 0;
if(tl <= mid)
li = qlca(ls(u),l,mid,tl,tr);
if(tr > mid)
ri = qlca(rs(u),mid + 1,r,tl,tr);
return (li && ri) ? lca(li,ri) : li + ri;
} //dfn_lca int H[N * 40];
int Hcnt;
int Head[N],Ls[N * 40],Rs[N * 40];
inline void merge(int las,int &now,int p,int l,int r){
if(!now)now = ++Hcnt;
Ls[now] = Ls[las];
Rs[now] = Rs[las];
H[now] = H[las] + 1;
if(l == r)
return ;
if(p <= mid){
Ls[now] = 0;
merge(Ls[las],Ls[now],p,l,mid);
}
if(p > mid){
Rs[now] = 0;
merge(Rs[las],Rs[now],p,mid + 1,r);
}
} inline ll find(int las,int now,int l,int r,int tl,int tr){
if(tl <= l && r <= tr)
return H[now] - H[las];
ll ans = 0;
if(tl <= mid)
ans += find(Ls[las],Ls[now],l,mid,tl,tr);
if(tr > mid)
ans += find(Rs[las],Rs[now],mid + 1,r,tl,tr);
return ans;
} //主席树 ll las = 0; inline void solve(ll now,ll l,ll r){
ll num = find(Head[dfn[now] - 1],Head[end[now]],1,n,l,r);
if(num == (r - l + 1)){
las = s[qlca(root,l,r)] - s[now];
std::cout<<las<<std::endl;
}else{
if(num != 0){
std::cout<<(las = 0)<<std::endl;
return ;
}
ll x = now;
for(int i = 29;i >= 0;--i){
int p = fa[x][i];
if(p != 0){
if(!(find(Head[dfn[p] - 1],Head[end[p]],1,n,l,r)))
x = fa[x][i];
}
}
if(fa[x][0] != 0 && !(find(Head[dfn[fa[x][0]] - 1],Head[end[fa[x][0]]],1,n,l,r)))
x = fa[x][0];
x = fa[x][0];
ll L1 = qlca(root,l,r);ll L2 = lca(now,L1);
if(L1 == L2)
las = s[now] - s[x];
else
las = s[now] - 2 * s[L2] + s[L1];
std::cout<<las<<std::endl;
return ;
}
} int main(){
scanf("%d%d",&n,&q);
for(int i = 1;i < n;++i){
ll x,y,w;
scanf("%d%d%d",&x,&y,&w);
add(x,y,w);
add(y,x,w);
}
dfs(1,0);
build(root);
for(int i = 1;i <= n;++i)
merge(Head[i - 1],Head[i],inv[i],1,n);
while(q -- ){
ll p,l,r;
scanf("%d%d%d",&p,&l,&r);
p ^= las;
l ^= las;
r ^= las;
solve(p,l,r);
}
}

『MdOI R1』Treequery的更多相关文章

  1. 洛谷 P6071 『MdOI R1』Treequery(LCA+线段树+主席树)

    题目链接 题意:给出一棵树,有边权,\(m\) 次询问,每次给出三个数 \(p,l,r\),求边集 \(\bigcap\limits_{i=l}^rE(p,i)\) 中所有边的权值和. 其中 \(E( ...

  2. P6072 『MdOI R1』Path

    考虑我们有这样操作. 我们只要维护两点在子树内和两点在子树外的异或和即可. 前者可以类似于线段树合并的trie树合并. 后者有两种做法: 一种是把dfn序翻倍:然后子树补变成了一个区间最大异或问题,可 ...

  3. 洛谷 P6072 -『MdOI R1』Path(回滚莫队+01-trie)

    题面传送门 又是 ix35 神仙出的题,先以 mol 为敬 %%% 首先预处理出根节点到每个点路径上权值的异或和 \(dis_i\),那么两点 \(a,b\) 路径上权值的异或和显然为 \(dis_a ...

  4. 洛谷 P6383 -『MdOI R2』Resurrection(DP)

    洛谷题面传送门 高速公路上正是补 blog 的时候,难道不是吗/doge,难不成逆在高速公路上写题/jy 首先形成的图显然是连通图并且有 \(n-1\) 条边.故形成的图是一棵树. 我们考虑什么样的树 ...

  5. LuoguP7337 『MdOI R4』Fun 题解

    Content 有 \(n\) 个人去打比赛.给出第 \(i\) 个人的交通方式 \(t_i\) 和颓废值 \(q_i\)(均以 \(0/1\) 表示).如果 \(t_i=1,q_i=1\) 的人数 ...

  6. 题解 P6745 『MdOI R3』Number

    前言 不知道是不是正解但是觉得挺好理解. 科学计数法 将一个数表示为\(a\times 10^x\) 的形式.其中\(a\leq10\),\(x\) 为整数. \(\sf Solution\) 其实这 ...

  7. 『TensorFlow Internals』笔记_源码结构

    零.资料集合 知乎专栏:Bob学步 知乎提问:如何高效的学习 TensorFlow 代码?. 大佬刘光聪(Github,简书) 开源书:TensorFlow Internals,强烈推荐(本博客参考书 ...

  8. 似魔鬼的 『 document.write 』

    在平时的工作中,楼主很少用 document.write 方法,一直觉得 document.write 是个危险的方法.楼主不用,并不代表别人不用,最近给维护的项目添了一点代码,更加深了我对 &quo ...

  9. 拾遗:『Linux Capability』

    『Linux Capability』 For the purpose of performing permission checks, traditional UNIX implementations ...

随机推荐

  1. 力扣 - 剑指 Offer 29. 顺时针打印矩阵

    题目 剑指 Offer 29. 顺时针打印矩阵 思路1 其实就是按照理解题目的意思一步步从外层到内层打印出来,同时将一个外层分成四个部分分步打印 可以用一个变量count来维护当前打印的第几层 判断打 ...

  2. 安装多个版本的 JDK

    安装多个版本的 JDK 刚刚开始学 Java 的时候安装了 JDK9 版本,后续发现还是 JDK8 使用的多些,而又不想删除原先版本 因此安装两个版本的 JDK 在需要是切换一下即可 1. 安装第一个 ...

  3. 2021.7.17 NKOJ周赛总结

    发现自己简直是个智障:T1模数写成1e9+9:T2居然没有考虑刚好一个周期的情况:T4用"%lld"读入"unsigned long long".~qwq~ T ...

  4. 实验 1: SDN拓扑实践

    (图片和文档是自己写的,因为在CSDN也写了,所以会有自己的水印) 一.实验目的 能够使用源码安装Mininet: 能够使用Mininet的可视化工具生成拓扑: 能够使用Mininet的命令行生成特定 ...

  5. cf12D Ball(MAP,排序,贪心思想)

    题意: N位女士一起聚在一个舞厅.每位女士有三个特征值B,I,R.分别代表美貌,智慧,富有. 对于一位女士而言,如果存在一个女士的B,I,R都分别大于她自己的B,I,R.则她自己会自杀. 统计总共有多 ...

  6. 分布式技术-Zookeeper概述

    概述 Zookeeper是一个开源的分布式的,为分布式应用提供协调服务的Apache项目 在大数据技术生态圈中,zookeeper(动物管理员),Hadoop(大象),Hive(蜜蜂),Pig(猪) ...

  7. kvm 安装 windows 虚拟机

    作者:SRE运维博客 博客地址: https://www.cnsre.cn/ 文章地址:https://www.cnsre.cn/posts/211108848062/ 相关话题:https://ww ...

  8. 01 | let 和 const语法 | es6

    01 | let 和 const语法 ES6新增了let命令,用来声明变量.它的用法类似于var,但也有区别 let 和 var 1.作用范围不同 var声明的变量在全局范围内都有效,所以全局只有一个 ...

  9. 『学了就忘』Linux基础命令 — 38、Linux中光盘的挂载

    目录 步骤一:创建一个空目录 步骤二:找到光盘的设备文件名称 步骤三:挂载光盘 步骤四:访问关盘中的数据 步骤五:卸载挂载点 问题:挂载点为什么要使用空目录 提示:关于Linux系统中光盘的挂载,我们 ...

  10. 解决SpringBoot项目部署到服务器后访问Tomcat后404,无法访问Controller