先处理出每一个i位置向左最远能到达的位置L[i]。每一次询问,要找到L,R区间中的p位置,p位置左边的L[i]都是小于L的,p位置开始,到R位置,L[i]都大于等于L,对于前者,最大值为p-L,后者求一个区间最大值即可。
#pragma comment(linker, "/STACK:1024000000,1024000000") #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<map> #include<set> #include<queue> #include<stack> #include<iostream> using namespace std; typedef long long LL; const double pi=acos(-1.0),eps=1e-8; void File() { freopen("D:\\in.txt","r",stdin); freopen("D:\\out.txt","w",stdout); } inline int read() { char c = getchar(); while(!isdigit(c)) c = getchar(); int x = 0; while(isdigit(c)) { x = x * 10 + c - ‘0‘; c = getchar(); } return x; } const int maxn=200000+10; int n,a[maxn],b[maxn],c[maxn],q,L[maxn]; int dp[maxn][30],f[maxn]; void RMQ_init() { for(int i=0;i<n;i++) dp[i][0]=f[i]; for(int j=1;(1<<j)<=n;j++) for(int i=0;i+(1<<j)-1<n;i++) dp[i][j]=max(dp[i][j-1],dp[i+(1<<(j-1))][j-1]); } int RMQ(int L,int R) { int k=0; while((1<<(k+1))<=R-L+1) k++; return max(dp[L][k],dp[R-(1<<k)+1][k]); } int main() { scanf("%d%d",&n,&q); for(int i=0;i<n;i++) scanf("%d",&a[i]),b[i]=a[i]; sort(b, b + n); int sz = unique(b, b + n) - b; for(int i=0;i<n;i++) a[i]=lower_bound(b, b + sz, a[i])-b+1; memset(c,-1,sizeof c); for(int i=0;i<n;i++) { if(i==0) L[0]=0,c[a[i]]=0; else L[i]=max(L[i-1],c[a[i]]+1),c[a[i]]=i; } for(int i=0;i<n;i++) f[i]=i-L[i]+1; RMQ_init(); for(int i=1;i<=q;i++) { int LL,RR; scanf("%d%d",&LL,&RR); int l=LL,r=RR,p=-1; while(l<=r) { int mid=(l+r)/2; if(L[mid]<LL) l=mid+1,p=mid; else r=mid-1; } int ans; if(p==-1) ans=RMQ(LL,RR); else if(p==RR) ans=RR-LL+1; else ans=max(p-LL+1,RMQ(p+1,RR)); printf("%d\n",ans); } return 0; }
时间: 2024-10-10 02:02:38