bzoj 2724 在线区间众数
如果不是在线,就是裸的莫队。
但这道题要求在线,然后就不会了。。
标程:
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 }
算法二:
1 /************************************************************** 2 Problem: 2724 3 User: idy002 4 Language: C++ 5 Result: Accepted 6 Time:17888 ms 7 Memory:2416 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 #include <cstring> 12 #include <cmath> 13 #include <algorithm> 14 #define maxn 40010 15 #define maxs 210 16 using namespace std; 17 18 int n, m; 19 int a[maxn]; 20 int lx[maxs], rx[maxs], mno[maxn], stot; 21 int fa[maxs][maxs], fn[maxs][maxs]; 22 int cnt[maxn], cura, curn; 23 int dl[maxn], dr[maxn], disc[maxn], md; 24 25 struct Pair { 26 int w, pos; 27 Pair(){} 28 Pair( int w, int pos ):w(w),pos(pos){} 29 }; 30 Pair vod[maxn]; 31 bool cmpwp( const Pair & a, const Pair & b ) { 32 return a.w<b.w || (a.w==b.w&&a.pos<b.pos); 33 } 34 bool cmpp( const Pair & a, const Pair & b ) { 35 return a.pos<b.pos; 36 } 37 38 void part() { 39 int len = (int)sqrt(n)+1; 40 stot = n/len+(n%len!=0); 41 for( int i=1; i<=stot; i++ ) { 42 lx[i] = rx[i-1]+1; 43 rx[i] = rx[i-1]+len; 44 if( i==stot ) rx[i]=n; 45 for( int j=lx[i]; j<=rx[i]; j++ ) 46 mno[j] = i; 47 } 48 } 49 void discard() { 50 for( int i=1; i<=n; i++ ) 51 disc[i] = a[i]; 52 sort( disc+1, disc+1+n ); 53 md = unique( disc+1, disc+1+n ) - disc - 1; 54 for( int i=1; i<=n; i++ ) { 55 a[i] = lower_bound( disc+1, disc+1+md, a[i] ) - disc; 56 vod[i] = Pair( a[i], i ); 57 } 58 sort( vod+1, vod+1+n, cmpwp ); 59 for( int i=1; i<=n; i++ ) { 60 if( vod[i].w!=vod[i-1].w ) { 61 dl[vod[i].w] = i; 62 dr[vod[i-1].w] = i-1; 63 } 64 } 65 dr[vod[n].w] = n; 66 } 67 int qu_cnt( int w, int l, int r ) { 68 return upper_bound(vod+dl[w],vod+dr[w]+1,Pair(w,r),cmpp) 69 - lower_bound(vod+dl[w],vod+dr[w]+1,Pair(w,l),cmpp); 70 } 71 void prep() { 72 for( int i=1; i<=stot; i++ ) { 73 memset( cnt, 0, sizeof(cnt) ); 74 for( int j=i; j<=stot; j++ ) { 75 for( int k=lx[j]; k<=rx[j]; k++ ) { 76 cnt[a[k]]++; 77 if( cnt[a[k]]>cnt[cura] || (cnt[a[k]]==cnt[cura] && a[k]<cura) ) 78 cura = a[k]; 79 } 80 fa[i][j] = cura; 81 fn[i][j] = cnt[cura]; 82 } 83 } 84 } 85 void update( int w, int l, int r ) { 86 int c = qu_cnt( w, l, r ); 87 if( c>curn || (c==curn && w<cura) ) { 88 cura = w; 89 curn = c; 90 } 91 } 92 int query( int l, int r ) { 93 int ml = mno[l], mr = mno[r]; 94 if( ml==mr ) { 95 cura = a[l]; 96 curn = qu_cnt( a[l], l, r ); 97 for( int j=l+1; j<=r; j++ ) 98 update(a[j],l,r); 99 return cura; 100 } 101 if( mno[l]==mno[l-1] ) ml++; 102 if( mno[r]==mno[r+1] ) mr--; 103 if( ml>mr ) { 104 cura = a[l]; 105 curn = qu_cnt( a[l], l, r ); 106 } else { 107 cura = fa[ml][mr]; 108 curn = fn[ml][mr]; 109 } 110 for( int j=l; j<lx[ml]; j++ ) 111 update(a[j],l,r); 112 for( int j=r; j>rx[mr]; j-- ) 113 update(a[j],l,r); 114 return cura; 115 } 116 117 int main() { 118 scanf( "%d%d", &n, &m ); 119 for( int i=1; i<=n; i++ ) 120 scanf( "%d", a+i ); 121 122 part(); 123 discard(); 124 prep(); 125 126 for( int i=1,x=0,l,r; i<=m; i++ ) { 127 scanf( "%d%d", &l, &r ); 128 l = (l+x-1)%n+1; 129 r = (r+x-1)%n+1; 130 if( l>r ) swap(l,r); 131 printf( "%d\n", x=disc[query(l,r)] ); 132 } 133 }