咱們把全部的蒲公英當作一個長度爲\(n\)的序列(\(a_1,a_2,...a_n\)),其中\(a_i\)爲一個正整數,表示第i棵蒲公英的種類的編號。
每次詢問一個區間\([l,r]\),你須要回答區間裏出現次數最多的是哪一種蒲公英,若是有若干種蒲公英出現次數相同,則輸出種類編號最小的那個。
注意,你的算法必須是在線的。html
第一行兩整數\(n,m\),表示有\(n\)棵蒲公英,mm次詢問。
接下來一行\(n\)個空格分隔的整數\(a_i\),表示蒲公英的種類。
接下來\(m\)行,每行兩個整數\(l_0,r_0\)。令上次的查詢結果爲\(x\)(若是是第一次查詢,則\(x=0\))。
令\(l=(l_0+x-1) mod (n+1), r=(r_0+x-1) mod (n+1)\)c++
輸出\(m\)行,每行一個整數,表示每次查詢的結果。算法
6 3 1 2 3 2 1 2 1 5 3 6 1 5
1 2 1
\(n \le 40000,m \le 50000,1 \le a_i \le 10^9n≤40000,m≤50000,1≤ai≤10^9\)spa
\(BZOJ2724\)
算法競賽進階指南\(P218-219\)code
這道題和\(數列分塊入門9\)蜜汁類似QAQ。htm
請自行參照個人\(數列分塊入門9題解\)blog
這裏僅放上代碼QAQ——ip
#include<bits/stdc++.h> using namespace std; #define MAXN 40005 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 = a[i], ans2 = t; if ( t == ans2 ) ans1 = min( ans1, a[i] ); } for ( int i = r; b[r] == b[i]; --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 main(){ scanf( "%d%d", &n, &T ); d = 0; while( ( 1 << d ) <= n ) d++; d = (int)( n / sqrt( 2 * T * 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); while( T-- ){ int l, r; scanf( "%d%d", &l, &r ); l = ( l + x - 1 ) % n + 1; r = ( r + x - 1 ) % n + 1; int t(min( l, r )); r = max( l, r ); l = t; printf( "%d\n", x = c[Get( l, r )] ); } return 0; }
數列分塊入門1get
數列分塊入門2input
蒲公英 <-