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 }
View Code

 

算法二:

  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 }
View Code

 

posted @ 2015-02-24 14:42  idy002  阅读(1294)  评论(0编辑  收藏  举报