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 }