欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

bzoj4358 perm

程序员文章站 2022-09-28 15:40:28
Description 给出一个长度为n的排列P(P1,P2,...Pn),以及m个询问。每次询问某个区间[l,r]中,最长的值域 连续段长度。 Input 第一行两个整数...

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

Source

By sumix173

思路很棒!

每个点记录两个信息:f[i][j]表示i的子树中深度为j的节点的个数。g[i][j]表示满足d[a]-2*d[lca(a,b)]=d[b]-2*d[lca(a,b)]的二元点对(a,b)的个数。

从下向上启发式合并,每次将轻儿子的信息合并到重儿子上,总的时间复杂度为O(nlogn)。在合并的过程中同时计算出答案。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<stack>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define pa pair<int,int>
#define maxn 50005
#define inf 1000000000
using namespace std;
int n,m,block,l,r,mx;
int a[maxn],pos[maxn],pl[maxn],pr[maxn],ans[maxn];
bool vst[maxn];
stack<pa> st;
struct data{int l,r,id;}b[maxn];
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
inline bool cmp(data x,data y)
{
	return pos[x.l]==pos[y.l]?x.r<y.r:x.l<y.l; .l="read();b[i].r=read();b[i].id=i;" block="int(sqrt(n));" bool="" data="" if="" inline="" int="" l="pos[b[i].l]*block;" mx="max(mx,tr-tl+1);" n="read();m=read();" pre="" r="l-1;" return="" tl="x,tr=x;" tmp="mx;" tr="pr[x+1];" void="" while=""><p>
</p>
   
</y.r:x.l<y.l;></pa></int,int></stack></algorithm></cmath></cstring></cstring></cstdio></iostream>