首页 > 其他分享 >【CF1491H Yuezheng Ling and Dynamic Tree】(分块)

【CF1491H Yuezheng Ling and Dynamic Tree】(分块)

时间:2023-03-17 18:44:43浏览次数:52  
标签:CF1491H Yuezheng int Tree sqrt leq LCA include 10

原题链接

题意

给定一棵大小为 \(n\) 的 \(1\) 为根节点的树,树用如下方式给出:输入 \(a_2,a_3,\dots,a_n\),保证 \(1\leq a_i<i\),将 \(a_i\) 与 \(i\) 连边形成一棵树。

接下来有两种操作:

  • 1 l r x 令 \(a_i=\max(a_i-x,1)(l\leq i\leq r)\)。
  • 2 u v 查询在当前的 \(a\) 数组构成的树上 \(u,v\) 的 LCA。

两种操作共有 \(q\) 个。

\(2\leq n,q\leq 10^5\),\(2\leq l\leq r\leq n\),\(1\leq x\leq 10^5\),\(1\leq u,v\leq n\)

思路

根据题意,\(a_i\) 只会减小,且减小若干次后就会恒等于 \(1\)。考虑对原序列进行分块操作。设块的大小为 \(\sqrt{n}\)。

对于块内的每个元素,维护其祖先节点中最大的不在这个块内的节点 \(b_i\)。每次查询 \(LCA\) 的时候只需要用类似于树链剖分求 \(LCA\) 的操作来进行即可。这部分的时间复杂为 \(O(n\sqrt{n})\)。

对于 \(i\),若 \(a_i\) 不在这个快内,那么直接令 \(b_i=a_i\);否则令 \(b_i=b_{a_i}\)。

对于零散块每次直接暴力修改,对于整块,也可以直接重构。由于每次 \(a_i\) 至少减少 \(1\),所以每个块至多被重构 \(\sqrt{n}\) 次,总的重构次数不会超过 \(O(\sqrt{n})\) 次。

code:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e5+10,B=405;
int cnt[N],pos[N],L[B],R[B],n,m,a[N],b[N],tag[N];
void update(int x)
{
	for(int i=L[x];i<=R[x];i++) a[i]=max(1,a[i]-tag[x]);tag[x]=0;
	for(int i=L[x];i<=R[x];i++) if(a[i]<L[x]) b[i]=a[i];else b[i]=b[a[i]];
}
void change(int l,int r,int z)
{
	if(pos[l]==pos[r])
	{
		for(int i=l;i<=r;i++) a[i]=max(1,a[i]-z);
		update(pos[r]);return ;
	}
	for(int i=l;i<=R[pos[l]];i++) a[i]=max(1,a[i]-z);update(pos[l]);
	for(int i=L[pos[r]];i<=r;i++) a[i]=max(1,a[i]-z);update(pos[r]);
	for(int i=pos[l]+1;i<pos[r];i++)
	{
		tag[i]=min(tag[i]+z,n);
		if(++cnt[i]<=B) update(i);
	}
}
int realb(int x){return max(1,b[x]-tag[pos[x]]);}
//b[x]要么是x直接指向的,要么是x在块内的某个祖先指向的,所以一定也要减去区间内的减标记 
int LCA(int x,int y)
{
	while(1)
	{
		if(pos[x]<pos[y]) swap(x,y);
		if(pos[x]!=pos[y]) x=realb(x);
		else
		{
			if(realb(x)!=realb(y)) x=realb(x),y=realb(y);
			else break;
		}
	}
	while(x!=y)
	{
		if(x<y) swap(x,y);
		x=max(1,a[x]-tag[pos[x]]);
	}
	return x;
}
int main()
{
	scanf("%d%d",&n,&m);for(int i=2;i<=n;i++) scanf("%d",&a[i]);
	for(int i=1;i<=n;i++) pos[i]=(i-1)/B+1;
	for(int i=1;i<=(n-1)/B+1;i++) L[i]=R[i-1]+1,R[i]=min(i*B,n),update(i);
	while(m--)
	{
		int opt,x,y,z;scanf("%d%d%d",&opt,&x,&y);
		if(opt==1) scanf("%d",&z),change(x,y,z);
		else printf("%d\n",LCA(x,y));
	}
	return 0;
}

标签:CF1491H,Yuezheng,int,Tree,sqrt,leq,LCA,include,10
From: https://www.cnblogs.com/ListenSnow/p/17227835.html

相关文章

  • Tree结构UI优化显示
    整体UI面板绘制参照https://www.cnblogs.com/babashi9527/p/17146645.html接着UI面板的设计;实现树形结构菜单的方式有很多种,每一种优化UI显示的方式可能存在较大差异;我......
  • 538. Convert BST to Greater Tree
    GivenaBinarySearchTree(BST),convertittoaGreaterTreesuchthateverykeyoftheoriginalBSTischangedtotheoriginalkeyplussumofallkeysgrea......
  • tkinter中treeview隔行显示不同的颜色
    隔行显示不同颜色的代码,这个牵涉到背景颜色,在3.8版的tkinter,要加多一些代码,才能让背景颜色起作用。这段要多加的代码就是:deffixed_map(option):return[elmforel......
  • list数组转tree树结构,并排序
    setTree(data){consttree=[];data.forEach(item=>{constchildren=this.list.filter(e=>e.parentId===item.id)if(children.length){......
  • WPF TreeView 样式
    一、前言TreeView控件在项目中使用比较频繁,普通的TreeView并不能满足我们的需求。因此我们需要滴对TreeView进行改造。下面的内容将介绍仿QQ联系人TreeView样式及TreeView......
  • [CF1788F] XOR, Tree, and Queries
    题目描述Youaregivenatreeof$n$vertices.Theverticesarenumberedfrom$1$to$n$.Youwillneedtoassignaweighttoeachedge.Lettheweight......
  • delphi 再说TcxDBTreeList
    1.当我们绑定好数据库之后,默认是全部折叠的,只显示  +全部    cxDBTreeList1.Root.getFirstChild.Expand(False);//只展开第一层目录cxDBTreeList1.FullE......
  • [LeetCode] 958. Check Completeness of a Binary Tree
    Giventhe root ofabinarytree,determineifitisa completebinarytree.Ina completebinarytree,everylevel,exceptpossiblythelast,iscompletely......
  • Solidity实现默克尔树 Merkle Tree
    ​​MerkleTree​​​,也叫默克尔树或哈希树,是区块链的底层加密技术,被BTC和Ethereum区块链广泛采用。​​MerkleTree​​​是一种自下而上构建的加密树,每个叶子是对应数据......
  • 【题解】P6071 『MdOI R1』Treequery
    题目描述给定一棵\(n\)个点的无根树,边有边权。令\(E(x,y)\)表示树上\(x,y\)之间的简单路径上的所有边的集合,特别地,当\(x=y\)时,\(E(x,y)=\varnothing\)。你需......