解析
预处理
用pre[i]表示以i结尾的最长完美序列起始点,用last[i]表示数字i最后出现的位置
那么可以得到递推式:
pre[i]=max(pre[i-1],last[x[i]]+1);
也就是说这个pre要么是受前一位一样的限制,要么是受自己的限制
用f[i]表示以i结尾的最长完美序列长度,那么显然:
f[i]=i-pre[i]+1;
以上可以用O(n)完成预处理
询问
接下来对于每次询问区间 [l,r] 中的每一位,只有两种可能:
1.pre在l左侧或l上
2.pre在l右侧
根据之前的递推式,pre显然单调不减。
因此这两种情况的分布具有单调性,我们就可以二分找出一个结点mid,使左侧及本身的pre均<=l(称为A),右侧pre均>l(称为B)
A:对于A的每一个元素,其在区间内可以达到的长度应该为i-l+1;那么显然让i=A中最大的值——mid时,取到最大值
B:对与B中的每一个元素,以其结尾的最大长度就是f[i],因此B的最优就是f在[now+1,r]中的最大值,用st表维护即可
A和B各自的最优取max,就是答案
单次询问时间复杂度O(logn)
代码
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <string>
#include <queue>
#include <string>
#include<map>
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a));
using namespace std;
const int N=2e5+100;
const int M=2e6+100;
int n,m,mod,ask;
int a,b,c;
int x[N],pre[N],last[M],f[N];
int dp[N][30],q[N];
int maxx(int a,int b){int k=q[(b-a)+1];int ans=max(dp[a][k],dp[b-(1<<k)+1][k]);return ans;
}
void Dp(){int o=0;for(int i=1;i<=n;i++){if(1<<o<=i) o++;q[i]=o-1;}for(int i=1;i<=n;i++) dp[i][0]=f[i];for(int k=1;k<=q[n];k++){for(int i=1;i+(1<<k)-1<=n;i++) dp[i][k]=max(dp[i][k-1],dp[i+(1<<(k-1))][k-1]);}
}
int find(int l,int r){int st=l,ed=r;while(st<ed){int mid=(st+ed+1)>>1;if(pre[mid]<=l) st=mid;else ed=mid-1;}return st;
}
int query(int l,int r){int now=find(l,r);int ans=now-l+1;
// int ans=0;
// for(int i=l;i<=r;i++){
// if(pre[i]<=l) ans=max(ans,i-l+1);
// else ans=max(ans,f[i]);
// }//ans=max(ans,maxx(now+1,r));
// for(int i=now+1;i<=r;i++) ans=max(ans,f[i]);ans=max(ans,maxx(now+1,r));return ans;
}
void read(){scanf("%d%d",&n,&m);for(int i=1;i<=n;i++) scanf("%d",&x[i]);
}
void solve(){for(int i=1;i<=n;i++){pre[i]=max(pre[i-1],last[x[i]]+1);last[x[i]]=i;f[i]=i-pre[i]+1;
// printf("%d ",pre[i]);}
// printf("\n");Dp();
}
void putout(){for(int i=1;i<=m;i++){scanf("%d%d",&a,&b);a++;b++;if(pre[b]<=a){printf("%d\n",b-a+1);continue;}printf("%d\n",query(a,b));}
}
int main(){read();solve();putout();return 0;
}
/*
9 15
1 2 3 4 5 6 7 8 9
*/
疑问
仔细看代码的童鞋会发现我的数组都开了2e6,但除了last之外应该开到2e5(n的范围)就够了
但一开始开2e5wa掉了。。。
期待看破其中玄机的dl评论区指点迷津awa
谢谢!