BZOJ4358permu kd-tree

Posted CQzhangyu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ4358permu kd-tree相关的知识,希望对你有一定的参考价值。

【BZOJ4358】permu

Description

给出一个长度为n的排列P(P1,P2,...Pn),以及m个询问。每次询问某个区间[l,r]中,最长的值域连续段长度。

Input

第一行两个整数n,m。
接下来一行n个整数,描述P。
接下来m行,每行两个整数l,r,描述一组询问。

Output

对于每组询问,输出一行一个整数,描述答案。

Sample Input

8 3
3 1 7 2 5 8 6 4
1 4
5 8
1 7

Sample Output

3
3
4

HINT

对于询问[1,4],P2,P4,P1组成最长的值域连续段[1,3];
对于询问[5,8],P8,P5,P7组成最长的值域连续段[4,6];
对于询问[1,7],P5,P7,P3,P6组成最长的值域连续段[5,8]。
1<=n,m<=50000

题解:一开始想莫队没想出来,然后就去膜拜了Claris的题解

然后下传标记的时候又有些不明白,于是又去膜拜了Claris的代码。。。

 

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=50010;
const int inf=1<<30;
int n,m,X,rt,D;
int p[maxn],v[maxn],ans[maxn];
struct kd
{
	int v[2],sm[2],sn[2],ls,rs,ts,val,tt,org,ht,hs,hv;
	kd () {}
	kd (int a,int b){v[0]=sm[0]=sn[0]=a,v[1]=sm[1]=sn[1]=b,ls=rs=ts=val=hs=hv=0,tt=ht=-inf;}
}t[maxn];
bool cmp(const kd &a,const kd &b)
{
	return (a.v[D]==b.v[D])?(a.v[D^1]<b.v[D^1]):(a.v[D]<b.v[D]);
}
inline int rd()
{
	int ret=0,f=1;	char gc=getchar();
	while(gc<\'0\'||gc>\'9\')	{if(gc==\'-\')f=-f;	gc=getchar();}
	while(gc>=\'0\'&&gc<=\'9\')	ret=ret*10+gc-\'0\',gc=getchar();
	return ret*f;
}
void ps(int x,int y)
{
	t[x].val+=y;
	if(t[x].val>t[x].hv)	t[x].hv=t[x].val;
	if(t[x].tt>=0)
	{
		t[x].tt+=y;
		if(t[x].tt>t[x].ht)	t[x].ht=t[x].tt;
	}
	else
	{
		t[x].ts+=y;
		if(t[x].ts>t[x].hs)	t[x].hs=t[x].ts;
	}
}
void pt(int x,int y)
{
	t[x].val=y;
	if(t[x].val>t[x].hv)	t[x].hv=t[x].val;
	t[x].tt=y,t[x].ts=0;
	if(t[x].tt>t[x].ht)	t[x].ht=t[x].tt;
}
void phs(int x,int y)
{
	t[x].hv=max(t[x].hv,t[x].val+y);
	if(t[x].ht>=0)	t[x].ht=max(t[x].ht,t[x].tt+y);
	else	t[x].hs=max(t[x].hs,t[x].ts+y);
}
void pht(int x,int y)
{
	t[x].hv=max(t[x].hv,y);
	t[x].ht=max(t[x].ht,y);
}
void pushup(int x,int y)
{
	t[x].sm[0]=max(t[x].sm[0],t[y].sm[0]);
	t[x].sm[1]=max(t[x].sm[1],t[y].sm[1]);
	t[x].sn[0]=min(t[x].sn[0],t[y].sn[0]);
	t[x].sn[1]=min(t[x].sn[1],t[y].sn[1]);
}
void pushdown(int x)
{
	if(t[x].hs)
	{
		if(t[x].ls)	phs(t[x].ls,t[x].hs);
		if(t[x].rs)	phs(t[x].rs,t[x].hs);
		t[x].hs=0;
	}
	if(t[x].ht>=0)
	{
		if(t[x].ls)	pht(t[x].ls,t[x].ht);
		if(t[x].rs)	pht(t[x].rs,t[x].ht);
		t[x].ht=-inf;
	}
	if(t[x].ts)
	{
		if(t[x].ls)	ps(t[x].ls,t[x].ts);
		if(t[x].rs)	ps(t[x].rs,t[x].ts);
		t[x].ts=0;
	}
	if(t[x].tt>=0)
	{
		if(t[x].ls)	pt(t[x].ls,t[x].tt);
		if(t[x].rs)	pt(t[x].rs,t[x].tt);
		t[x].tt=-inf;
	}
}
int build(int l,int r,int d)
{
	if(l>r)	return 0;
	int mid=(l+r)>>1;
	D=d,nth_element(t+l,t+mid,t+r+1,cmp);
	t[mid].ls=build(l,mid-1,d^1),t[mid].rs=build(mid+1,r,d^1);
	if(t[mid].ls)	pushup(mid,t[mid].ls);
	if(t[mid].rs)	pushup(mid,t[mid].rs);
	return mid;
}
void updata(int x)
{
	if(!x)	return;
	if(t[x].sn[0]>X||t[x].sm[1]<X)
	{
		pt(x,0);
		return ;
	}
	if(t[x].sm[0]<=X&&t[x].sn[1]>=X)
	{
		ps(x,1);
		return ;
	}
	pushdown(x);
	if(t[x].v[0]<=X&&t[x].v[1]>=X)	t[x].val++,t[x].hv=max(t[x].hv,t[x].val);
	else	t[x].val=0;
	updata(t[x].ls),updata(t[x].rs);
}
void dfs(int x)
{
	if(!x)	return ;
	pushdown(x),ans[t[x].org]=t[x].hv;
	dfs(t[x].ls),dfs(t[x].rs);
}
int main()
{
	n=rd(),m=rd();
	int i,a,b;
	for(i=1;i<=n;i++)	p[rd()]=i;
	for(i=1;i<=m;i++)	a=rd(),b=rd(),t[i]=kd(a,b),t[i].org=i;
	rt=build(1,m,0);
	for(i=1;i<=n;i++)
		X=p[i],updata(rt);
	dfs(rt);
	for(i=1;i<=m;i++)	printf("%d\\n",ans[i]);
	return 0;
}

 

以上是关于BZOJ4358permu kd-tree的主要内容,如果未能解决你的问题,请参考以下文章

[bzoj4358] permu

bzoj4358: permu

BZOJ4358: permu 莫队算法

bzoj 4358 Permu - 莫队算法 - 链表

bzoj4358 perm

[bzoj4066/2683]简单题_KD-Tree