首页 > 其他分享 >P5314 [Ynoi2011] ODT

P5314 [Ynoi2011] ODT

时间:2023-12-07 21:33:40浏览次数:41  
标签:int Ynoi2011 Sp ODT 信息 Add include P5314 op

好题,牛牛的一个套路。

先树剖一下,我们可以很简单的用树状数组维护每个点的真实值。

对于每个点只维护所有轻儿子的信息,对于每次询问的时候暴力加入当前点,重儿子以及父亲的信息,查询第 \(k\) 大,再删除信息即可。

考虑链修改的影响。因为只维护的是轻儿子的信息,那么只有链上的所有轻边会修改。

具体的,设当前轻边 \((x,y)\),\(y\) 是父亲,先在 \(y\) 中删除原来 \(x\) 的信息,再加入当前 \(x\) 的真实信息即可。

树剖链查询的时候只会经过 \(O(\log n)\) 的轻边,用平衡树维护每个点的信息即可,直接用 pb_ds 就好了!

默认 \(n,m\) 同阶,复杂度 \(O(n \log^2 n)\)。

小细节:树剖最后链修改 \(x,y\) 跳到一条重链时,如果一端是重链头,需要对它的父亲进行修改。

#include<bits/stdc++.h>
using namespace std;
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;

typedef long long ll;
const int N=1e6+3;
int n,m,a[N];
vector<int>ve[N];
struct Nod
{
	int x,id;
	friend bool operator <(Nod a,Nod b){return a.x!=b.x?a.x<b.x:a.id<b.id;}
};
tree<Nod,null_type,less<Nod>,rb_tree_tag,tree_order_statistics_node_update>tr[N];
struct BIT
{
	int tr[N];
	void Add(int x,int y){for(;x<=n;x+=x&-x)tr[x]+=y;}
	int Ask(int x){int s=0;for(;x;x-=x&-x)s+=tr[x];return s;}
	void Mdf(int l,int r,int d){Add(l,d);Add(r+1,-d);}
}T;
struct ShuPou
{
	int sz[N],fa[N],dep[N],hson[N],tim,top[N],dfn[N],pos[N];
	void Dfs1(int x)
	{
		sz[x]=1;dep[x]=dep[fa[x]]+1;
		for(int y:ve[x])if(y!=fa[x])
		{
			fa[y]=x;Dfs1(y);sz[x]+=sz[y];
			if(sz[hson[x]]<sz[y])hson[x]=y;
		}
	}
	void Dfs2(int x,int tp)
	{
		top[x]=tp;pos[x]=++tim;dfn[tim]=x;T.Mdf(tim,tim,a[x]);
		if(hson[x])Dfs2(hson[x],tp);
		for(int y:ve[x])if(y!=fa[x]&&y!=hson[x])Dfs2(y,y),tr[x].insert({a[y],y});
	}
	void Upd(int x,int y,int z)
	{
		while(top[x]!=top[y])
		{
			if(dep[top[x]]<dep[top[y]])swap(x,y);
			int tp=top[x];tr[fa[tp]].erase({a[tp],tp});
			T.Mdf(pos[tp],pos[x],z);a[tp]=T.Ask(pos[tp]);
			tr[fa[tp]].insert({a[tp],tp});x=fa[top[x]];
		}
		if(dep[x]<dep[y])swap(x,y);
		if(dep[y]!=dep[top[y]]||!fa[y]){T.Mdf(pos[y],pos[x],z);return;}
		tr[fa[y]].erase({a[y],y});T.Mdf(pos[y],pos[x],z);
		a[y]=T.Ask(pos[y]);tr[fa[y]].insert({a[y],y});
	}
}Sp;
void Add(int x,int y){if(y)tr[x].insert({T.Ask(Sp.pos[y]),y});}
void Del(int x,int y){if(y)tr[x].erase({T.Ask(Sp.pos[y]),y});}
int main()
{
	ios::sync_with_stdio(false),cin.tie(0),cout.tie(0); 
	cin>>n>>m;
	for(int i=1;i<=n;i++)cin>>a[i];
	for(int i=1,x,y;i<n;i++)cin>>x>>y,ve[x].push_back(y),ve[y].push_back(x);
	Sp.Dfs1(1);Sp.Dfs2(1,1);
	while(m--)
	{
		int op,x,y,z;cin>>op>>x>>y;
		if(op==1){cin>>z;Sp.Upd(x,y,z);continue;}
		Add(x,x);Add(x,Sp.hson[x]);Add(x,Sp.fa[x]);
		cout<<tr[x].find_by_order(y-1)->x<<'\n';
		Del(x,x);Del(x,Sp.hson[x]);Del(x,Sp.fa[x]);
	}
}

有任何疑惑欢迎与我交流。

标签:int,Ynoi2011,Sp,ODT,信息,Add,include,P5314,op
From: https://www.cnblogs.com/Hanghang007/p/17884025.html

相关文章

  • P5311 [Ynoi2011] 成都七中
    我永远喜欢数据结构。题目传送门给出\(n\)个点的树,点有颜色\(a_i\)。有\(q\)次询问,每次询问给出\(l,r,x\),求保留\([l,r]\)范围内的节点时,\(x\)所在联通块中有多少种本质不同的颜色。询问之间相互独立。不保留一个点的定义是,将这个点以及与其相邻的边全部删除。......
  • P5309 [Ynoi2011] 初始化
    题目传送门本来不想写这道\(shabi\)卡肠题的,但还是写了。分块+根号分治。考虑对\(x\)的大小分类讨论:若\(x>=\sqrt{n}\),很明显最多只会加\(\sqrt{n}\)次,暴力加即可,用分块维护每个块内的\(sum\),查询就直接散块加上整块即可。若\(x<\sqrt{n}\),考虑累加\(x,y\)相同的......
  • note ODT
    (珂朵莉图压压惊)适用场景:不断区间修改、区间询问,数据随机ODT:olddrivertree(老司机树),又名珂朵莉树,是一个骗分的好东西。其内部是基于std::set实现的,而std::set是基于红黑树实现的,所以我觉得应该是算法,但是对于ODT究竟是算法还是数据结构有争议。在随机数据下跑得飞快,吊打......
  • MethodTimer.Fody 统计代码执行时间
    开发时,经常需要了解代码的执行效率,可以借助MethodTimer.Fody这个开源库。主页:https://github.com/Fody/MethodTimer1、安装Nuget包:Install-PackageMethodTimer.Fody2、AddtoFodyWeavers.xml<Weavers><MethodTimer/></Weavers>3、代码部分,在需要统计的方法上头加上......
  • 珂朵莉树(ODT)
    处理区间赋值问题的神器!珂朵莉树的实现非常简单(baoli),建树时把区间的左右端点和权值作为一个节点全扔到std::set(或者链表)中维护即可split:核心操作之一,将一段区间提取出来,在此之上进行一些操作assign:核心操作之二,也是降低珂朵莉树时间复杂度的重要操作,把一段区间推平赋值,......
  • 「Ynoi2011」成都七中
    「Ynoi2011」成都七中题意:询问\(([l,r],x)\),表示将树中编号在\([l,r]\)内的所有节点保留,求\(x\)所在连通块中颜色种类数可以转化为从\(x\)出发且只经过节点范围在\([l,r]\)的路径上的颜色种类数,是路径问题且多次询问,所以可以考虑点分树但是可以发现,一个节点的答案可......
  • ODT
    别写。Useless.TrysomeODT.CF915E\(\color{#52C41A}{\text{Accepted}}\)CF896C\(\color{#52C41A}{\text{Accepted}}\)P3740\(\color{#52C41A}{\text{Accepted}}\)......
  • 【模板】ODT | Old Driver Tree | 珂朵莉树
    postedon2021-04-0220:38:49|under学术|source这个东西本身不常用,但是这个维护连续段的写法很常用。标签:暴力、数据结构、std::set#include<set>template<cla......
  • DDR3原理(ODT)
    一、存储器的分类存储器一般来说可以分为内部存储器(内存),外部存储器(外存),缓冲存储器(缓存)以及闪存这几个大类。内存也称为主存储器,位于系统主机板上,可以同CPU直接......
  • Microsoft 365 开发:如何通过脚本批量获取用户MFA状态以及Default MethodType
    Blog链接:​​​https://blog.51cto.com/13969817​​今天给大家分享一下如何通过脚本检验用户是否启用了MFA以及DefaultMethodType,首先我们确保环境:·      部署了MS......