题目链接

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

其中 \(E(u,v)\) 为点 \(u\) 到点 \(v\) 的路径中经过的边的集合。

强制在线。

\(1 \leq n \leq 2 \times 10^5\)。

果然是神仙 ix35 wdl 出的题啊……

不妨以 \(1\) 为根,做一遍 dfs 求出它们的 dfs 序,以及它们到根的距离 \(d_i\)。

每次询问,我们求出 \(l,l+1,\dots,r\) 中所有点的 LCA,假设为 \(t\)。

我们将 \([l,r]\) 中的点分成三个集合:

  • 集合 A:在 \(p\) 的子树中。
  • 集合 B:不在 \(p\) 的子树中,但是与 \(p\) 在根节点的同一子树中。
  • 集合 C:与 \(p\) 在根节点的不同子树中。

    接下来就是分情况讨论了:
  1. 如果所有点都属于集合 A,那么答案就是 \(d_t-d_p\)
  2. 如果有的点都属于集合 A,有的点不属于集合 A,那么答案为 \(0\)。
  3. 如果没有点属于集合 A,那么从 \(p\) 不断地往上跳,直到 \([l,r]\) 中至少有一个点在当前点的子树内,记当前所在的点为 \(f\),那么又有两种情况:
  • \(f\) 在 \(t\) 上方,那么答案为 \(d_p+d_t-2 \times d_f\)
  • \(f\) 在 \(t\) 下方,那么答案为 \(d_p-d_f\)

    口胡完了,实现也不难:
  • 求区间 LCA,建一棵线段树,节点上维护 LCA。
  • 判断有多少个点在 \(x\) 的子树中:注意到 \(x\) 子树的 dfs 序是一个连续的区间,可以想到主席树。以 dfs 序为节点下标建一棵主席树。第 \(i\) 棵树的第 \(j\) 个位置上的数表示节点 \(1\) 到节点 \(i\) 中有多少个点的 dfs 序为 \(j\)。
  • 往上跳:倍增
//Coded by tzc_wk
/*
数据不清空,爆零两行泪。
多测不读完,爆零两行泪。
边界不特判,爆零两行泪。
贪心不证明,爆零两行泪。
D P 顺序错,爆零两行泪。
大小少等号,爆零两行泪。
变量不统一,爆零两行泪。
越界不判断,爆零两行泪。
调试不注释,爆零两行泪。
溢出不 l l,爆零两行泪。
忘文件操作,爆零两行泪。
*/
#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define fz(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define foreach(it,v) for(__typeof(v.begin()) it=v.begin();it!=v.end();it++)
#define all(a) a.begin(),a.end()
#define giveup(...) return printf(__VA_ARGS__),0;
#define fill0(a) memset(a,0,sizeof(a))
#define fill1(a) memset(a,-1,sizeof(a))
#define fillbig(a) memset(a,0x3f,sizeof(a))
#define fillsmall(a) memset(a,0xcf,sizeof(a))
#define mask(a) (1ll<<(a))
#define maskx(a,x) ((a)<<(x))
#define _bit(a,x) (((a)>>(x))&1)
#define _sz(a) ((int)(a).size())
#define filei(a) freopen(a,"r",stdin);
#define fileo(a) freopen(a,"w",stdout);
#define fileio(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout)
#define eprintf(...) fprintf(stderr,__VA_ARGS__)
#define put(x) putchar(x)
#define eoln put('\n')
#define space put(' ')
#define y1 y_chenxiaoyan_1
#define y0 y_chenxiaoyan_0
//#define int long long
typedef pair<int,int> pii;
inline int read(){
int x=0,neg=1;char c=getchar();
while(!isdigit(c)){
if(c=='-') neg=-1;
c=getchar();
}
while(isdigit(c)) x=x*10+c-'0',c=getchar();
return x*neg;
}
inline void print(int x){
if(x<0){
putchar('-');
print(abs(x));
return;
}
if(x<=9) putchar(x+'0');
else{
print(x/10);
putchar(x%10+'0');
}
}
inline int qpow(int x,int e,int _MOD){
int ans=1;
while(e){
if(e&1) ans=ans*x%_MOD;
x=x*x%_MOD;
e>>=1;
}
return ans;
}
int n=read(),m=read();
struct edge{
int u,v,w;
edge(){/*Problemsetter of P6071 AK IOI*/}
edge(int _u,int _v,int _w){
u=_u;v=_v;w=_w;
}
};
vector<edge> g[200005];
int idx,dist[200005],dep[200005],dfn[200005],fa[200005][23],sz[200005],id[200005];
inline void dfs(int x,int f){
dfn[x]=++idx;
id[idx]=x;
fa[x][0]=f;
sz[x]=1;
foreach(it,g[x]){
int y=it->v,z=it->w;
if(y==f) continue;
dist[y]=dist[x]+z;
dep[y]=dep[x]+1;
dfs(y,x);
sz[x]+=sz[y];
}
}
inline int LCA(int x,int y){
if(dep[x]<dep[y]) swap(x,y);
for(int i=22;i>=0;i--){
if(dep[x]-(1<<i)>=dep[y]) x=fa[x][i];
}
if(x==y) return x;
for(int i=22;i>=0;i--){
if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
}
return fa[x][0];
}
struct SegTree{
struct node{
int l,r,lca;
} s[200005<<2];
inline void build(int k,int l,int r){
s[k].l=l;s[k].r=r;
if(l==r){
s[k].lca=l;
return;
}
int mid=(l+r)>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
s[k].lca=LCA(s[k<<1].lca,s[k<<1|1].lca);
}
inline int query(int k,int l,int r){
if(l<=s[k].l&&s[k].r<=r){
return s[k].lca;
}
int mid=(s[k].l+s[k].r)>>1;
if(r<=mid) return query(k<<1,l,r);
else if(l>mid) return query(k<<1|1,l,r);
else return LCA(query(k<<1,l,mid),query(k<<1|1,mid+1,r));
}
} segt;
struct hjtree{
struct node{
int l,r,ch[2],cnt;
} s[200005<<5];
int ncnt=0,rt[200005];
inline void build(int &k,int l,int r){
k=++ncnt;s[k].l=l;s[k].r=r;s[k].cnt=0;
if(l==r) return;
int mid=(l+r)>>1;
build(s[k].ch[0],l,mid);
build(s[k].ch[1],mid+1,r);
}
inline void modify(int &k,int pre,int x){
k=++ncnt;s[k]=s[pre];s[k].cnt++;
if(s[k].l==s[k].r) return;
int mid=(s[k].l+s[k].r)>>1;
if(x<=mid) modify(s[k].ch[0],s[pre].ch[0],x);
else modify(s[k].ch[1],s[pre].ch[1],x);
s[k].cnt=s[s[k].ch[0]].cnt+s[s[k].ch[1]].cnt;
}
inline int query(int k,int l,int r){
// cout<<s[k].l<<" "<<s[k].r<<" "<<s[k].cnt<<endl;
if(l<=s[k].l&&s[k].r<=r) return s[k].cnt;
int mid=(s[k].l+s[k].r)>>1;
if(r<=mid) return query(s[k].ch[0],l,r);
else if(l>mid) return query(s[k].ch[1],l,r);
else return query(s[k].ch[0],l,mid)+query(s[k].ch[1],mid+1,r);
}
} hjt;
inline int getcnt(int p,int l,int r){
// cout<<hjt.rt[0]<<" "<<hjt.rt[l-1]<<endl;
// cout<<hjt.query(hjt.rt[l-1],dfn[p],dfn[p]+sz[p]-1)<<endl;
return hjt.query(hjt.rt[r],dfn[p],dfn[p]+sz[p]-1)-hjt.query(hjt.rt[l-1],dfn[p],dfn[p]+sz[p]-1);
}
signed main(){
fz(i,1,n-1){
int u=read(),v=read(),w=read();
g[u].push_back(edge(u,v,w));
g[v].push_back(edge(v,u,w));
}
dfs(1,0);
// fz(i,1,n) cout<<dfn[i]<<endl;
fz(i,1,22) fz(j,1,n) fa[j][i]=fa[fa[j][i-1]][i-1];
segt.build(1,1,n);
hjt.build(hjt.rt[0],1,n);
fz(i,1,n) hjt.modify(hjt.rt[i],hjt.rt[i-1],dfn[i]);
int ans=0;
// cout<<LCA(2,5)<<endl;
while(m--){
int p=read(),l=read(),r=read();
p^=ans;l^=ans;r^=ans;
int lc=segt.query(1,l,r);
int num=getcnt(p,l,r);
// cout<<"lc="<<lc<<"\tnum="<<num<<endl;
if(num==r-l+1) ans=dist[lc]-dist[p];
else if(num>0) ans=0;
else{
int cur=p;
for(int i=20;i>=0;i--){
if(fa[cur][i]&&getcnt(fa[cur][i],l,r)==0)
cur=fa[cur][i];
}
cur=fa[cur][0];
// cout<<"cur="<<cur<<endl;
if(dist[cur]<dist[lc]) ans=dist[p]+dist[lc]-(dist[cur]<<1);
else ans=dist[p]-dist[cur];
}
printf("%d\n",ans);
}
return 0;
}

洛谷 P6071 『MdOI R1』Treequery(LCA+线段树+主席树)的更多相关文章

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

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

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

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

  3. 『MdOI R1』Treequery

    我们可以思考怎么做呢. 首先我们需要进行一些分类讨论: 我们先思考一下如果所有关键点都在 \(p\) 的子树内, 那显然是所有关键点的 \(Lca\) 到 \(p\) 距离. 如果所有关键点一些在 \ ...

  4. P6072 『MdOI R1』Path

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

  5. 洛谷P3402 【模板】可持久化并查集 [主席树,并查集]

    题目传送门 可持久化并查集 n个集合 m个操作 操作: 1 a b 合并a,b所在集合 2 k 回到第k次操作之后的状态(查询算作操作) 3 a b 询问a,b是否属于同一集合,是则输出1否则输出0 ...

  6. 洛谷3月月赛 R1 Step! ZERO to ONE

    洛谷3月月赛 R1 Step! ZERO to ONE 普及组难度 290.25/310滚粗 t1 10分的日语翻译题....太难了不会... t2 真·普及组.略 注意长为1的情况 #include ...

  7. 「洛谷4197」「BZOJ3545」peak【线段树合并】

    题目链接 [洛谷] [BZOJ]没有权限号嘤嘤嘤.题号:3545 题解 窝不会克鲁斯卡尔重构树怎么办??? 可以离线乱搞. 我们将所有的操作全都存下来. 为了解决小于等于\(x\)的操作,那么我们按照 ...

  8. 「洛谷3870」「TJOI2009」开关【线段树】

    题目链接 [洛谷] 题解 来做一下水题来掩饰ZJOI2019考炸的心情QwQ. 很明显可以线段树. 维护两个值,\(Lazy\)懒标记表示当前区间是否需要翻转,\(s\)表示区间还有多少灯是亮着的. ...

  9. 洛谷P1395 会议(CODEVS.3029.设置位置)(求树的重心)

    To 洛谷.1395 会议 To CODEVS.3029 设置位置 题目描述 有一个村庄居住着n个村民,有n-1条路径使得这n个村民的家联通,每条路径的长度都为1.现在村长希望在某个村民家中召开一场会 ...

随机推荐

  1. Scrum Meeting 0429

    零.说明 日期:2021-4-29 任务:简要汇报两日内已完成任务,计划后两日完成任务 一.进度情况 组员 负责 两日内已完成的任务 后两日计划完成的任务 qsy PM&前端 完成部分后端管理 ...

  2. [对对子队]会议记录5.22(Scrum Meeting9)

    今天已完成的工作 梁河览 ​ 工作内容:修改第一到九关新手引导,修复关卡选择bug ​ 相关issue:优化初步导出版本 ​ 相关签入:fix:修改第一关到第九关的新手引导和地图场景的bug 马嘉 ​ ...

  3. CentOS系统优化一键配置脚本

    #!/usr/bin/env bash PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin export P ...

  4. JavaAgent型内存马基础

    Java Instrumentation ​ java Instrumentation指的是可以用独立于应用程序之外的代理(agent)程序来监测和协助运行在JVM上的应用程序.这种监测和协助包括但不 ...

  5. STM32采集AD的输入阻抗问题

    在做一款消费电子产品时,需要采集电池电压(3.3V-4.2V),同时在休眠的时候希望尽量减小待机电流.电池电压采集电路采用两个1%的300K电阻进行分压,由该电路引起的待机电路为4.2/(300+30 ...

  6. Spring事务不生效问题

    事务未生效可能造成严重的数据不一致性问题,因而保证事务生效至关重要.Spring事务是通过Spring aop实现的,所以不生效的本质问题是spring aop没生效,或者说没有代理成功,所以有必要了 ...

  7. 使用Visual Studio 2019将ASP.NET Core发布为linux-arm64程序

    前言 前段时间入手了一台树莓派4B,一直闲置未使用,最近工作需要,要在上面跑下.NET Core程序,由于树莓派4B使用的是ARM架构,并且支持64位操作系统,为了充分发挥树莓派性能,我的这台树莓派安 ...

  8. AppScan 10安装使用

    一.简介 AppScan是IBM的一款web安全扫描工具,具有利用爬虫技术进行网站安全渗透测试的能力,能够根据网站入口自动摸取网页链接进行安全扫描,提供了扫描.报告和修复建议等功能. appscan有 ...

  9. RISCV 入门 (学习笔记)

    文章目录 1. risv 相关背景 1.1 arm 授权费 1.2 riscv 发展历史 1.3 riscv 风险 2. 指令集 2.1 可配置的通用寄存器组 2.2 规整的指令编码 2.3 简洁的存 ...

  10. Linux usb 2. 协议分析

    文章目录 0. 背景 1. USB 协议传输格式 1.1 Packet 1.1.1 Token Packet 1.1.2 Data Packet 1.1.3 Handshake Packet 1.1. ...