zoukankan      html  css  js  c++  java
  • 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
    ", x=query(l,r) );
    136     }
    137 }
    View Code
  • 相关阅读:
    【WEBAPI】Passing multiple POST parameters to Web API Controller Methods
    【WEBAPI】常用参数传递方法总结
    JavaScript面向对象静态方法私有方法公有方法特权方法
    javascript 封装
    javascript 获取 浏览器body高宽
    Fiddler 教程
    预加载下一张图片
    div页面居中
    关于模块化加载
    chrome本地不能操作iframe
  • 原文地址:https://www.cnblogs.com/idy002/p/4298977.html
Copyright © 2011-2022 走看看