如果不是在线,就是裸的莫队。

但这道题要求在线,然后就不会了。。

标程:

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

相关文章:

  • 2022-01-07
  • 2021-08-12
  • 2021-07-07
  • 2021-11-14
  • 2021-08-23
  • 2021-08-29
  • 2022-02-12
  • 2021-05-31
猜你喜欢
  • 2021-10-15
  • 2022-12-23
  • 2022-03-01
  • 2021-10-23
  • 2021-04-16
  • 2021-10-12
  • 2021-08-14
相关资源
相似解决方案