时间限制: 1 Sec 内存限制: 128 MB
题目描述
给你一个长度为N的序列,定义“完美序列”是一段区间满足区间内使用的数互不相同 询问M次,问区间[L,R]之间最长完美序列的长度
输入
9 2
2 5 4 1 2 3 6 2 4
0 8
2 6
输出
6
5
提示
N,M<=200000,序列中数的大小绝对值不超过
题解:
这题还是有很多坑的吧,大家要小心,仔细看样例。
这是一道较复杂的 题
我们令 表示盈利值 最近出现的位置,一开始全部是
我们先令 表示以第 个数为结尾的最长完美序列
表示第 个数为结尾最长完美序列的长度
很显然
和 都是在 能解决的
由 的递推式可知, 的值是一个非递增的序列,那么对于一个询问区间 ,该区间的 值可能会出现:左边一部分的 值不在区间内,即小于 ,而右边一部分的 值大于等于 ,由于 值有单调性,所以这个分界点我们可以用二分得到
令这个分界点为
那么整个区间最长完美长度,可以分两部分来解决。其中左边部分的最大值很显然为 ,而右边部分由于 值大于等于 ,所以就是求 之间 数组的最大值
我们再令 表示以 开始之后 个中 数组的最大值
这个我们便可以用
#include<bits/stdc++.h>
#define N 200005
using namespace std;
int last[N*10],b[N*10],a[N*10],st[N*10],f[N*10],maxn[N][30];
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
st[i]=max(st[i-1],last[a[i]+1000000]+1);
f[i]=i-st[i]+1;
maxn[i][0]=f[i];
last[a[i]+1000000]=i;
}
for(int j=1;j<20;j++)
for(int i=1;i<=n+1-(1<<j);i++)
maxn[i][j]=max(maxn[i][j-1],maxn[i+(1<<(j-1))][j-1]);
for(int i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
x++,y++;
int l=x,r=y;
while(x<y)
{
int mid=(x+y)>>1;
if(st[mid]<l)x=mid+1;else y=mid;
}
if(st[x]<l)x=x+1;
int nmax=0;
if(x<=r)
{
int k=log2(double(r-x+1));
nmax=max(maxn[x][k],maxn[r-(1<<k)+1][k]);
}
printf("%d\n",max(nmax,x-l));
}
return 0;
}