bzoj 2821 分块

 

分块:

先预处理,将原序列分成长度为len的许多块,计算从第i块到第j块的答案,(可以做到O(n*n/len))。

每次询问时,将询问的区间分成三部分,:左边,中间,右边,中间是尽量大的一个块区间,其答案已经计算得到,左右两边加起来最多有2*len个元素,暴力计算其对答案的影响。O(q*len*f(n)),f(n)是暴力加入一个元素的代价。

这道题f(n)是log(n)

总的复杂度:f(n) = O( n*n/len + q*len*log(n) ),

当len = n*(q*log(n))-1/2时取最小值.

 

  1 /**************************************************************
  2     Problem: 2821
  3     User: idy002
  4     Language: C++
  5     Result: Accepted
  6     Time:24352 ms
  7     Memory:13728 kb
  8 ****************************************************************/
  9  
 10 #include <cstdio>
 11 #include <cstring>
 12 #include <cmath>
 13 #include <algorithm>
 14 #define maxn 100010
 15 #define maxs 1510
 16 #define isok(a) ((a)>0&&!((a)&1))
 17 using namespace std;
 18  
 19 int n, c, m;
 20 int a[maxn], f[maxs][maxs];
 21 int lx[maxn], rx[maxn], mno[maxn], stot;
 22 int cnt[maxn], cur_ans;
 23 int vs[maxn], vt[maxn], vp[maxn];
 24 bool met[maxn];
 25  
 26 struct Pair {
 27     int w, pos;
 28     Pair(){}
 29     Pair( int w, int pos ) : w(w), pos(pos) {}
 30 };
 31 Pair vod[maxn];
 32 bool cmpwp( const Pair & a, const Pair & b ) {
 33     return a.w<b.w || (a.w==b.w && a.pos<b.pos);
 34 }
 35 bool cmpp( const Pair & a, const Pair & b ) {
 36     return a.pos<b.pos;
 37 }
 38  
 39 void part() {
 40     int len = (int)(double)sqrt((double)n/(log((double)n)/log(2)))+1;
 41     stot = n/len + (n%len!=0);
 42     for( int i=1; i<=stot; i++ ) {
 43         lx[i] = rx[i-1]+1;
 44         rx[i] = rx[i-1]+len;
 45         if( i==stot ) rx[i] = n;
 46         for( int j=lx[i]; j<=rx[i]; j++ ) 
 47             mno[j] = i;
 48     }
 49 }
 50 inline void update( int oldv, int newv ) {
 51     bool od, nw;
 52     od = isok(oldv); 
 53     nw = isok(newv);
 54     if( od && !nw ) cur_ans--;
 55     else if( !od && nw ) cur_ans++;
 56 }
 57  
 58 void prep() {
 59     for( int i=1; i<=n; i++ ) 
 60         vod[i] = Pair(a[i],i);
 61     sort( vod+1, vod+1+n, cmpwp );
 62     for( int i=1; i<=n; i++ ) {
 63         if( vod[i].w!=vod[i-1].w ) 
 64             vs[vod[i].w] = vt[vod[i-1].w] = i;
 65     }
 66     vt[vod[n].w] = n+1;
 67     for( int i=1; i<=n; i++ ) vp[i] = vod[i].pos;
 68  
 69     for( int i=1; i<=stot; i++ ) {
 70         for( int j=i; j<=stot; j++ ) {
 71             for( int k=lx[j]; k<=rx[j]; k++ ) {
 72                 update( cnt[a[k]], cnt[a[k]]+1 );
 73                 cnt[a[k]]++;
 74             }
 75             f[i][j] = cur_ans;
 76         }
 77         cur_ans = 0;
 78         memset( cnt, 0, sizeof(cnt) );
 79     }
 80 }
 81  
 82 int qu_cnt( int w, int l, int r ) {
 83     return upper_bound( vp+vs[w], vp+vt[w], r )
 84         -  lower_bound( vp+vs[w], vp+vt[w], l );
 85 }
 86 int query( int l, int r ) {
 87     int ml=mno[l], mr=mno[r];
 88     int rt;
 89     if( ml==mr ) {
 90         for( int j=l; j<=r; j++ ) {
 91             update( cnt[a[j]], cnt[a[j]]+1 );
 92             cnt[a[j]]+=1;
 93         }
 94         rt = cur_ans;
 95         cur_ans = 0;
 96         for( int j=l; j<=r; j++ ) 
 97             cnt[a[j]]--;
 98         return rt;
 99     }
100     if( mno[l]==mno[l-1] ) ml++;
101     if( mno[r]==mno[r+1] ) mr--;
102     cur_ans = f[ml][mr];
103     for( int j=l; j<lx[ml]; j++ ) {
104         if( met[a[j]] ) continue;
105         met[a[j]] = true;
106         int t1 = qu_cnt(a[j],l,r);
107         int t2 = qu_cnt(a[j],lx[ml],rx[mr]);
108         update( t2, t1 );
109     }
110     for( int j=r; j>rx[mr]; j-- ) {
111         if( met[a[j]] ) continue;
112         met[a[j]] = true;
113         int t1 = qu_cnt(a[j],l,r);
114         int t2 = qu_cnt(a[j],lx[ml],rx[mr]);
115         update( t2, t1 );
116     }
117     rt = cur_ans;
118  
119     cur_ans = 0;
120     for( int j=l; j<lx[ml]; j++ ) met[a[j]]=false;
121     for( int j=r; j>rx[mr]; j-- ) met[a[j]]=false;
122     return rt;
123 }
124  
125 int main() {
126     scanf( "%d%d%d", &n, &c, &m );
127     for( int i=1; i<=n; i++ ) scanf( "%d", a+i );
128     part();
129     prep();
130     for( int i=1,x=0,l,r; i<=m; i++ ) {
131         scanf( "%d%d", &l, &r );
132         l = (l+x)%n+1;
133         r = (r+x)%n+1;
134         if( l>r ) swap(l,r);
135         printf( "%d\n", x=query(l,r) );
136     }
137 }
View Code
posted @ 2015-02-24 21:45  idy002  阅读(167)  评论(0编辑  收藏  举报