CodeChef QCHEF Chef and Problems (分塊)
阿新 • • 發佈:2018-12-12
題意:
一個數列,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)); } }