如果不是在线,就是裸的莫队。
但这道题要求在线,然后就不会了。。
标程:
http://hi.baidu.com/__vani/item/ecc63f3527395283c2cf2945
算法主要是分块,然后处理处f[i][j]从第i块到第j块这个块区间的信息。
第一个算法的思想是每个块区间除了维护答案,还记录了该块区间中每个数的个数,这样可以快速添加增加一个数到该区间,所以他查询的时候就是找到查询区间的完整的块,然后向左右扩展,记录下答案,再撤销修改。设块的长度为L,则时间复杂度为:O(m*n+n*n*n/L/L),L=n1/3时最小。
第二个算法不需要记下每个块区间中每个数出现次数,只记下众数及出现次数,查询时,因为可能的答案是查询区间包含的块区间的众数以及两端不在块区间的数,至于两边的数,可以枚举判断它是否可能是众数。O(m*n0.5*logn)
算法一:
1 /************************************************************** 2 Problem: 2724 3 User: idy002 4 Language: C++ 5 Result: Accepted 6 Time:7156 ms 7 Memory:251984 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 #include <cmath> 12 #include <iostream> 13 #include <algorithm> 14 #define maxn 40010 15 #define maxs 40 16 using namespace std; 17 18 struct Cnt { 19 int cnt[maxn], mw; 20 inline void operator +=( int w ) { 21 cnt[w]++; 22 update(w); 23 } 24 inline void update( int w ) { 25 if( cnt[w]>cnt[mw] || (cnt[w]==cnt[mw] && w<mw) ) 26 mw = w; 27 } 28 }; 29 30 int n, m; 31 int w[maxn]; 32 int lx[maxs], rx[maxs], mccno[maxn], stot; 33 int disc[maxn], md; 34 Cnt f[maxs][maxs], cur; 35 36 37 void partition() { 38 int len = (int)pow(n,2.0/3.0)+1; 39 stot = n/len+(n%len!=0); 40 rx[0] = 0; 41 for( int i=1; i<=stot; i++ ) 42 rx[i]=rx[i-1]+len, lx[i]=rx[i-1]+1; 43 rx[stot] = min( rx[stot], n ); 44 for( int i=1; i<=stot; i++ ) 45 for( int j=lx[i]; j<=rx[i]; j++ ) 46 mccno[j] = i; 47 } 48 void discard() { 49 for( int i=1; i<=n; i++ ) 50 disc[i] = w[i]; 51 sort( disc+1, disc+1+n ); 52 md = unique( disc+1, disc+1+n ) - disc - 1; 53 for( int i=1; i<=n; i++ ) 54 w[i] = lower_bound( disc+1, disc+1+md, w[i] ) - disc; 55 } 56 void prep() { 57 for( int i=1; i<=stot; i++ ) 58 for( int j=lx[i]; j<=rx[i]; j++ ) { 59 f[i][i].cnt[w[j]]++; 60 f[i][i].update(w[j]); 61 } 62 for( int i=1; i<=stot; i++ ) { 63 for( int j=i+1; j<=stot; j++ ) { 64 for( int k=1; k<=md; k++ ) 65 f[i][j].cnt[k] = f[i][j-1].cnt[k]+f[j][j].cnt[k]; 66 f[i][j].cnt[0] = 0; 67 f[i][j].mw = 0; 68 for( int k=1; k<=md; k++ ) 69 f[i][j].update(k); 70 } 71 } 72 } 73 int query( int l, int r ) { 74 int rt; 75 int sl=mccno[l], sr=mccno[r]; 76 if( sl==sr ) { 77 for( int j=l; j<=r; j++ ) { 78 cur.cnt[w[j]]++; 79 cur.update( w[j] ); 80 } 81 rt = cur.mw; 82 cur.mw = 0; 83 for( int j=l; j<=r; j++ ) 84 cur.cnt[w[j]]--; 85 return rt; 86 } 87 int ml = mccno[l], mr = mccno[r]; 88 if( mccno[l]==mccno[l-1] ) ml++; 89 if( mccno[r]==mccno[r+1] ) mr--; 90 Cnt &cur = f[ml][mr]; 91 int oldw = cur.mw; 92 for( int j=l; j<lx[ml]; j++ ) cur += w[j]; 93 for( int j=rx[mr]+1; j<=r; j++ ) cur += w[j]; 94 rt = cur.mw; 95 for( int j=l; j<lx[ml]; j++ ) cur.cnt[w[j]]--; 96 for( int j=rx[mr]+1; j<=r; j++ ) cur.cnt[w[j]]--; 97 cur.mw = oldw; 98 return rt; 99 } 100 int main() { 101 scanf( "%d%d", &n, &m ); 102 for( int i=1; i<=n; i++ ) 103 scanf( "%d", w+i ); 104 105 discard(); 106 partition(); 107 prep(); 108 109 int x = 0; 110 for( int i=1,l,r; i<=m; i++ ) { 111 scanf( "%d%d", &l, &r ); 112 l = ( l+x-1 )%n+1; 113 r = ( r+x-1 )%n+1; 114 if( r<l ) swap(l,r); 115 printf( "%d\n", x=disc[query(l,r)] ); 116 } 117 }