「分塊系列」數列分塊入門9 解題報告

數列分塊入門9

題意歸納

靜態,區間求衆數。html

寫在前面

還記得分塊1就提到的關於塊的大小有時要經過計算麼??在這裏就獲得了體現!c++

正題

爲了方便起見,咱們設把數列分紅K塊~spa

這道題很值得思考。code

先離散化~ 而後記錄位置~htm

咱們能夠考慮,對於L ~ R之間的衆數只有多是如下三種狀況:blog

  • b[L]塊中L以後的部分
  • b[R]塊中R以前的部分
  • b[L] + 1塊到b[R] - 1塊的衆數

第三條能夠預處理出。get

而後對於每次詢問,直接枚舉上述三種狀況便可。it

代碼

#include<bits/stdc++.h>
using namespace std;
#define MAXN 50005

int n, m, T;
int a[MAXN], b[MAXN], c[MAXN];
int d, f[2000][2000];
int s[MAXN];
vector<int> p[MAXN];

int Count( int l, int r, int x ){
    return upper_bound( p[x].begin(), p[x].end(), r ) - lower_bound( p[x].begin(), p[x].end(), l );
}

int Get( int l, int r ){
    if ( b[l] == b[r] ){
        int ans1(0), ans2(0);
        for ( int i = l; i <= r; ++i ){
            int t(Count( l, r, a[i] ));
            if ( t > ans2 ) ans1 = a[i], ans2 = t;
            if ( t == ans2 ) ans1 = min( ans1, a[i] );
        }
        return ans1;
    }
    int ans1(f[b[l] + 1][b[r] - 1]), ans2(Count( l, r, ans1 ));
    for ( int i = l; b[l] == b[i]; ++i ){
        int t(Count( l, r, a[i] ));
        if ( t == ans2 ) ans1 = min( ans1, a[i] );
        if ( t > ans2 ) ans1 = a[i], ans2 = t;
    }
    for ( int i = r; b[r] == b[i]; --i ){
        int t(Count( l, r, a[i] ));
        if ( t == ans2 ) ans1 = min( ans1, a[i] );
        if ( t > ans2 ) ans1 = a[i], ans2 = t;
    }
    return ans1;
}

int main(){
    scanf( "%d", &n );
    d = 0;
    while( ( 1 << d ) <= n ) d++;
    d--;
    d = (int)( n / sqrt( 2 * n * d ) );
    for ( int i = 1; i <= n; ++i ){
        scanf( "%d", &a[i] ); c[i] = a[i]; b[i] = ( i - 1 ) / d + 1;
    }
    sort( c + 1, c + n + 1 );//離散化
    m = unique( c + 1, c + n + 1 ) - c - 1;
    for ( int i = 1; i <= n; ++i ) a[i] = lower_bound( c + 1, c + m + 1, a[i] ) - c;
    for ( int i = 1; i <= n; ++i ) p[a[i]].push_back(i);//每一個元素都記錄位置
    
    for ( int i = 1; i <= b[n]; ++i ){
        memset( s, 0, sizeof s );
        int ans1(0), ans2(0);
        for ( int j = ( i - 1 ) * d + 1; j <= n; ++j ){
            s[a[j]]++;
            if ( s[a[j]] == ans2 ) ans1 = min( ans1, a[j] );
            if ( s[a[j]] > ans2 ) ans1 = a[j], ans2 = s[a[j]];
            if ( b[j + 1] != b[j] ) f[i][b[j]] = ans1;
        }
    }
    int x(0);
    for ( int T = 1; T <= n; ++T ){
        int l, r;
        scanf( "%d%d", &l, &r );
        int t(min( l, r )); r = max( l, r ); l = t;
        printf( "%d\n", x = c[Get( l, r )] );
    }
    return 0;
}

總結

分塊大法入門1~9就這麼結束惹,但分塊這個博大精深的暴力遠遠不止這些, 還有待你們去探索(((((ી(・◡・)ʃ)))))入門

數列分塊系列目錄

數列分塊入門1class

數列分塊入門2

數列分塊入門3

數列分塊入門4

數列分塊入門5

數列分塊入門6

數列分塊入門7

數列分塊入門8

數列分塊入門9 <-

蒲公英

公主的朋友

相關文章
相關標籤/搜索