题意:
一个数列,m次查询,每次查询[L,R]中,一样的数字的最远距离
思路:
分块,对于每一个块,维护fi[i][j] (第j个块,i出现最前的位置),la[i][j] (第j个块,i的出现最后的位置),再维护ans[i][j](第i个块到第j个块,出现最多的次数),对于每次查询,如果L,R处于同一个块,则直接暴力统计,否则,先扫左边,不断更新某个数出现最后的位置,同时用la[a[i]][block[r-1]-i更新答案,同理,右边也是这样,用i-fi[a[i]][block[l]+1]跟新答案,同时利用之前左边更新的最后位置继续更新答案,最后再用ans[block[l]+1][block[r]-1]更新答案即可。
错误及反思:
破机子卡常
代码:
#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define pf push_front
#define lb lower_bound
#define ub upper_bound
#define mst(x,a) memset(x,a,sizeof(x))
#define all(x) (x).begin(),(x).end()
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
typedef pair<int,int> pii;
typedef long long ll;
typedef vector<int> vi;
#define fi first
#define se second
#define sz(x) ((int)x.size())
#define cl(x) x.clear()
const int mod = 1000000007;
const int N = 100010;
const int M = 330;
void MOD(ll &a){
if(a>=mod) a-=mod;}
void MOD(ll &a,ll c){
if(a>=c) a-=c;}
void ADD(ll &a,ll b){
a+=b; MOD(a);}
void ADD(ll &a,ll b,ll c){
a+=b;MOD(a,c);}
ll qpow(ll a,ll b){
ll ans=1;while(b){
if(b&1)ans=ans*a%mod;a=a*a%mod;b/=2;}return ans;}
ll qpow(ll a,ll b,ll c){
ll ans=1;while(b){
if(b&1)ans=ans*a%c;a=a*a%c;b/=2;}return ans;}int n,m,k,blocks,tot,times;
int fi[N][M],la[N][M],ans[M][M],a[N],block[N],last[N],tim[N];int cal(int l,int r){
int res=0;for(int i=blocks*(l-1)+1;i<=blocks*l;i++)res=max(res,la[a[i]][r]-i);return res;
}
int query(int l,int r){
int res=0;times++;if(block[l]==block[r]){
for(int i=l;i<=r;i++){
if(times==tim[a[i]]) res=max(res,i-last[a[i]]);else last[a[i]]=i,tim[a[i]]=times;}return res;}res=ans[block[l]+1][block[r]-1];for(int i=l;i<=blocks*block[l];i++){
if(times==tim[a[i]]) res=max(res,i-last[a[i]]);else last[a[i]]=i,tim[a[i]]=times;res=max(res,la[a[i]][block[r]-1]-i);}for(int i=(block[r]-1)*blocks+1;i<=r;i++){
if(times==tim[a[i]]) res=max(res,i-last[a[i]]);else last[a[i]]=i,tim[a[i]]=times;res=max(res,i-fi[a[i]][block[l]+1]);}return res;
}
int main(){
scanf("%d%d%d",&n,&m,&k);blocks=320; tot=320;for(int i=1;i<=n;i++) scanf("%d",&a[i]),block[i]=(i-1)/blocks+1;for(int i=1;i<=n;i++) la[a[i]][block[i]]=i;for(int i=n;i>=1;i--) fi[a[i]][block[i]]=i;for(int i=1;i<=m;i++){
for(int j=1;j<=blocks;j++)if(!la[i][j]) la[i][j]=la[i][j-1];for(int j=blocks;j>=1;j--)if(!fi[i][j]) fi[i][j]=fi[i][j+1];}for(int i=tot;i>=1;i--)for(int j=i;j<=tot;j++)ans[i][j]=max(max(ans[i+1][j],ans[i][j-1]),cal(i,j));for(int i=0;i<k;i++){
int l,r; scanf("%d%d",&l,&r);printf("%d\n",query(l,r));}
}