洛谷 P6071 『MdOI R1』Treequery(LCA+线段树+主席树)
题意:给出一棵树,有边权,\(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\) 在根节点的不同子树中。
接下来就是分情况讨论了: 
- 如果所有点都属于集合 A,那么答案就是 \(d_t-d_p\)
 - 如果有的点都属于集合 A,有的点不属于集合 A,那么答案为 \(0\)。
 - 如果没有点属于集合 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+线段树+主席树)的更多相关文章
- 洛谷 P6072 -『MdOI R1』Path(回滚莫队+01-trie)
		
题面传送门 又是 ix35 神仙出的题,先以 mol 为敬 %%% 首先预处理出根节点到每个点路径上权值的异或和 \(dis_i\),那么两点 \(a,b\) 路径上权值的异或和显然为 \(dis_a ...
 - 洛谷 P6383 -『MdOI R2』Resurrection(DP)
		
洛谷题面传送门 高速公路上正是补 blog 的时候,难道不是吗/doge,难不成逆在高速公路上写题/jy 首先形成的图显然是连通图并且有 \(n-1\) 条边.故形成的图是一棵树. 我们考虑什么样的树 ...
 - 『MdOI R1』Treequery
		
我们可以思考怎么做呢. 首先我们需要进行一些分类讨论: 我们先思考一下如果所有关键点都在 \(p\) 的子树内, 那显然是所有关键点的 \(Lca\) 到 \(p\) 距离. 如果所有关键点一些在 \ ...
 - P6072 『MdOI R1』Path
		
考虑我们有这样操作. 我们只要维护两点在子树内和两点在子树外的异或和即可. 前者可以类似于线段树合并的trie树合并. 后者有两种做法: 一种是把dfn序翻倍:然后子树补变成了一个区间最大异或问题,可 ...
 - 洛谷P3402 【模板】可持久化并查集 [主席树,并查集]
		
题目传送门 可持久化并查集 n个集合 m个操作 操作: 1 a b 合并a,b所在集合 2 k 回到第k次操作之后的状态(查询算作操作) 3 a b 询问a,b是否属于同一集合,是则输出1否则输出0 ...
 - 洛谷3月月赛 R1 Step! ZERO to ONE
		
洛谷3月月赛 R1 Step! ZERO to ONE 普及组难度 290.25/310滚粗 t1 10分的日语翻译题....太难了不会... t2 真·普及组.略 注意长为1的情况 #include ...
 - 「洛谷4197」「BZOJ3545」peak【线段树合并】
		
题目链接 [洛谷] [BZOJ]没有权限号嘤嘤嘤.题号:3545 题解 窝不会克鲁斯卡尔重构树怎么办??? 可以离线乱搞. 我们将所有的操作全都存下来. 为了解决小于等于\(x\)的操作,那么我们按照 ...
 - 「洛谷3870」「TJOI2009」开关【线段树】
		
题目链接 [洛谷] 题解 来做一下水题来掩饰ZJOI2019考炸的心情QwQ. 很明显可以线段树. 维护两个值,\(Lazy\)懒标记表示当前区间是否需要翻转,\(s\)表示区间还有多少灯是亮着的. ...
 - 洛谷P1395 会议(CODEVS.3029.设置位置)(求树的重心)
		
To 洛谷.1395 会议 To CODEVS.3029 设置位置 题目描述 有一个村庄居住着n个村民,有n-1条路径使得这n个村民的家联通,每条路径的长度都为1.现在村长希望在某个村民家中召开一场会 ...
 
随机推荐
- Scrum Meeting 0429
			
零.说明 日期:2021-4-29 任务:简要汇报两日内已完成任务,计划后两日完成任务 一.进度情况 组员 负责 两日内已完成的任务 后两日计划完成的任务 qsy PM&前端 完成部分后端管理 ...
 - [对对子队]会议记录5.22(Scrum Meeting9)
			
今天已完成的工作 梁河览  工作内容:修改第一到九关新手引导,修复关卡选择bug  相关issue:优化初步导出版本  相关签入:fix:修改第一关到第九关的新手引导和地图场景的bug 马嘉  ...
 - CentOS系统优化一键配置脚本
			
#!/usr/bin/env bash PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin export P ...
 - JavaAgent型内存马基础
			
Java Instrumentation  java Instrumentation指的是可以用独立于应用程序之外的代理(agent)程序来监测和协助运行在JVM上的应用程序.这种监测和协助包括但不 ...
 - STM32采集AD的输入阻抗问题
			
在做一款消费电子产品时,需要采集电池电压(3.3V-4.2V),同时在休眠的时候希望尽量减小待机电流.电池电压采集电路采用两个1%的300K电阻进行分压,由该电路引起的待机电路为4.2/(300+30 ...
 - Spring事务不生效问题
			
事务未生效可能造成严重的数据不一致性问题,因而保证事务生效至关重要.Spring事务是通过Spring aop实现的,所以不生效的本质问题是spring aop没生效,或者说没有代理成功,所以有必要了 ...
 - 使用Visual Studio 2019将ASP.NET Core发布为linux-arm64程序
			
前言 前段时间入手了一台树莓派4B,一直闲置未使用,最近工作需要,要在上面跑下.NET Core程序,由于树莓派4B使用的是ARM架构,并且支持64位操作系统,为了充分发挥树莓派性能,我的这台树莓派安 ...
 - AppScan 10安装使用
			
一.简介 AppScan是IBM的一款web安全扫描工具,具有利用爬虫技术进行网站安全渗透测试的能力,能够根据网站入口自动摸取网页链接进行安全扫描,提供了扫描.报告和修复建议等功能. appscan有 ...
 - RISCV 入门 (学习笔记)
			
文章目录 1. risv 相关背景 1.1 arm 授权费 1.2 riscv 发展历史 1.3 riscv 风险 2. 指令集 2.1 可配置的通用寄存器组 2.2 规整的指令编码 2.3 简洁的存 ...
 - 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. ...