zoukankan      html  css  js  c++  java
  • 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
    ", 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
    ", x=disc[query(l,r)] );
    132     }
    133 }
    View Code
  • 相关阅读:
    写爬虫,怎么可以不会正则呢?
    从 Scrapy 学习模块导入技巧
    博客已搬家至CSDN
    更改JDK默认编码,解决DBeaver乱码问题
    【2020面试】- Java中常见集合的默认大小以及扩容机制
    【2020面试】- CAS机制与自旋锁
    【2020面试】- filter和interceptor的区别
    【20k中级开发】-面试题201117
    【开发笔记】
    RPC 调用和 HTTP 调用的区别
  • 原文地址:https://www.cnblogs.com/idy002/p/4298696.html
Copyright © 2011-2022 走看看