1. 程式人生 > >Loj 6285. 數列分塊入門 9

Loj 6285. 數列分塊入門 9

return 次數 push print min 實現 離散化 vector 每一個

鏈接:

https://loj.ac/problem/6285

思路:

離散化處理下就好了,具體解釋在代碼裏、

ps:

小新新別看了,你學不會的

實現代碼:

#include<bits/stdc++.h>
using namespace std;
const int M = 1e5 + 10;
int n,block,idx,a[M],bl[M],f[510][510],val[M],cnt[M];
vector<int>ve[M];
void pre(int x){  //預處理
    memset(cnt,0,sizeof(cnt));
    
int mx = 0, ans = 0; for(int i = (x - 1)*block+1;i <= n;i ++){ cnt[a[i]]++; int t = bl[i]; if(cnt[a[i]] > mx||(cnt[a[i]]==mx&&val[a[i]]<val[ans])) //如果在當前區間出現次數比最大值或者和最大值一樣但是值比最大值小,那麽更新最大值 ans = a[i],mx = cnt[a[i]]; f[x][t] = ans; //代表 x塊 到 t塊中的最小眾數
} } int query(int l,int r,int x){ //在ve[ai]二分尋找在l,r區間的a[i]的數量 int t = upper_bound(ve[x].begin(),ve[x].end(),r) - lower_bound(ve[x].begin(),ve[x].end(),l); return t; } int query(int l,int r){ int ans,mx; ans = f[bl[l]+1][bl[r]-1]; //完整塊的查詢 mx = query(l,r,ans);
//非完整塊的查詢 for(int i = l;i <= min(bl[l]*block,r);i ++){ int t = query(l,r,a[i]); if(t > mx||(t == mx&&val[a[i]] < val[ans])) ans = a[i],mx = t; } if(bl[l] != bl[r]){ for(int i = (bl[r]-1)*block+1;i <= r;i ++){ int t = query(l,r,a[i]); if(t > mx||(t == mx&&val[a[i]] < val[ans])) ans = a[i],mx = t; } } return ans; } map<int,int>mp; int main() { int l,r; scanf("%d",&n); block = sqrt(n); for(int i = 1;i <= n;i ++){ scanf("%d",&a[i]); if(!mp[a[i]]){ mp[a[i]] = ++idx; //離散化 val[idx] = a[i]; //val數組儲存離散化之前的值 } a[i] = mp[a[i]]; //離散化 ve[a[i]].push_back(i); //將每個a[i]出現的下標存到a[i]對應的vecotr裏 } for(int i = 1;i <= n;i ++) bl[i] = (i - 1)/block + 1; for(int i = 1;i <= bl[n];i ++) pre(i); //預處理每一個塊 for(int i = 1;i <= n;i ++) { scanf("%d%d",&l,&r); if(l > r) swap(l,r); printf("%d\n",val[query(l,r)]); } return 0; }

Loj 6285. 數列分塊入門 9