L. Lookup Performance(二分+主席树)

Posted issue是fw

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了L. Lookup Performance(二分+主席树)相关的知识,希望对你有一定的参考价值。

LINK

给定一颗二叉搜索树

q q q次询问给定区间 [ l , r ] [l,r] [l,r],问从根节点执行 l o o k u p ( 1 , l , r ) lookup(1,l,r) lookup(1,l,r)函数共执行多少次


设节点 x x x中权值最小权值为 m i x mi_x mix,最大的为 m x x mx_x mxx

如果能访问到节点 x x x,说明 x x x的父节点 r r r一定

①.不满足 L < = m i r & & m x r < = R L<=mi_r\\&\\&mx_r<=R L<=mir&&mxr<=R

②.不满足 m x r < L mx_r<L mxr<L R < m i r R<mi_r R<mir

①好办,我们把所有节点的 m i r mi_r mir装进数组 z z z中,把 m x r mx_r mxr装进 y y y

二分找到多少节点的 L < = m i r L<=mi_r L<=mir,二分找到多少节点的 m x r < = R mx_r<=R mxr<=R

②的话,我们按照 m i r mi_r mir排序,按照 m i r mi_r mir的排名为索引, m x r mx_r mxr为节点权值插入主席树

那么对于 [ L , R ] [L,R] [L,R]区间,先二分一个 i d id id使得 r ∈ [ i d , n ] r\\in[id,n] r[id,n] m i r mi_r mir都大于等于 L L L

那么就是要求这个区间有多少权值小于等于 R R R

主席树模板题

#include <bits/stdc++.h>
using namespace std;
#define mid ((l+r)>>1)
const int maxn = 1e7+19;
const int inf = 1e9+1;
vector<int>vec[maxn],z,y;
typedef pair<int,int>p;
vector<p>both;
int k[maxn],n,mi[maxn],mx[maxn];
void dfs(int u)
{
	mi[u] = k[u], mx[u] = k[u];
	for(auto v:vec[u] )
	{
		dfs( v );
		mi[u] = min( mi[u],mi[v] );
		mx[u] = max( mx[u],mx[v] );
	}
}
int siz[maxn],ls[maxn],rs[maxn],id,root[maxn];
void update(int &rt,int pre,int l,int r,int val)
{
	rt = ++id;
	ls[rt] = ls[pre], rs[rt] = rs[pre], siz[rt] = siz[pre]+1;
	if( l==r )	return;
	if( val<=mid )	update(ls[rt],ls[pre],l,mid,val);
	else	update( rs[rt],rs[pre],mid+1,r,val );
}
int ask(int rt,int pre,int l,int r,int L,int R)//查询权值为[-inf,val]之间的点数 
{
	if( l>=L && r<=R )	return siz[rt]-siz[pre];
	if( l>R || r<L )	return 0;
	if( l==r )	return 1;
	return ask( ls[rt],ls[pre],l,mid,L,R)+ask( rs[rt],rs[pre],mid+1,r,L,R );
}
int main()
{
	int n;  cin >> n;
	for(int i=1;i<=n;i++)
	{
		int l,r; scanf("%d%d%d",&l,&r,&k[i]);
		if( l ) vec[i].push_back( l );
		if( r )	vec[i].push_back( r );
	}
	dfs( 1 );
	for(int i=1;i<=n;i++)
	{
		z.push_back( mi[i] ),y.push_back( mx[i] );
		both.push_back( p(mi[i],mx[i] ) );
	}
	sort( both.begin(),both.end() );
	sort( z.begin(),z.end() );
	sort( y.begin(),y.end() );
	for(int i=1;i<=n;i++)
		update( root[i],root[i-1],-inf,inf,both[i-1].second );
	int q; cin >> q;
	while( q-- )
	{
		int l,r; scanf("%d%d",&l,&r);
		int ld = n-(upper_bound(z.begin(),z.end(),r)-z.begin()+1)+1;
		int rd = lower_bound(y.begin(),y.end(),l)-y.begin();
		int id = lower_bound(z.begin(),z.end(),l)-z.begin()+1;
		
	//	cout << ask( root[n],root[id-1],-inf,inf,-inf,r ) << "sssssssss" << endl;
		int now = n-ld-rd-ask(root[n],root[id-1],-inf,inf,-inf,r);

		printf("%d\\n",now<<1|1 );	
	}
}

以上是关于L. Lookup Performance(二分+主席树)的主要内容,如果未能解决你的问题,请参考以下文章

Performance - Inefficient use of keySet iterator instead of entrySet iterator

L. 变量的作用域

学术报告 | Dr. L. Ruby Leung

L. Twice Equation ACM Nanning 2017

Problem L. World Cup

L. Right Build bfs