1. 程式人生 > >CodeChef QCHEF Chef and Problems (分塊)

CodeChef QCHEF Chef and Problems (分塊)

題意:

        一個數列,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));
    }
}