zoukankan      html  css  js  c++  java
  • BZOJ 2724 分块统计

    区间众数

    先离散化,学到了lagoon的lower_bound+unique的离散化,比我写的简单多了

    预处理分成sqrt(n)块,记录d[i][j]和p[i][j]分别表示从i块起始位置到j块终止位置的众数出现次数和这个数是谁

    开一个数组,记录每个数的位置,使得同类的相邻,同类数的坐标升序排列。

    对于询问:

    对于同一块内或者相邻块内的,直接暴力。

    对于不同块内的,统计出非整块的区间内的所有出现过的数字,然后对这些数字在二分存储位置的数组,统计块内这个数出现的次数。然后结合d[i][j]和p[i][j]就可以得出答案了

    View Code
      1 #include <iostream>
      2 #include <cstring>
      3 #include <cstdio>
      4 #include <algorithm>
      5 #include <cstdlib>
      6 #include <cmath>
      7 
      8 #define N 1000000
      9 #define M 2000
     10 
     11 using namespace std;
     12 
     13 int sz,tot;
     14 int lt[N],rt[N],ed[M],st[M],sum[N];
     15 int q[N],cs[N],p[M][M],d[M][M];
     16 int n,m;
     17 int val[N],a[N];
     18 int ef[N];
     19 int bx,by;
     20 
     21 inline void getblock()
     22 {
     23     sz=sqrt(n); tot=n/sz;
     24     for(int i=1;i<=tot;i++)
     25     {
     26         st[i]=ed[i-1]+1;
     27         ed[i]=st[i]+sz-1;
     28     }
     29     if(ed[tot]!=n)
     30     {
     31         ++tot;
     32         st[tot]=ed[tot-1]+1;
     33         ed[tot]=n;
     34     }
     35     int cnum,csum;
     36     for(int i=1;i<=tot;i++)
     37     {
     38         csum=0;
     39         memset(cs,0,sizeof cs);
     40         for(int j=i;j<=tot;j++)
     41         {
     42             for(int k=st[j];k<=ed[j];k++)
     43             {
     44                 cs[val[k]]++;
     45                 if(cs[val[k]]>csum)
     46                 {
     47                     csum=cs[val[k]];
     48                     cnum=val[k];
     49                 }
     50                 else if(cs[val[k]]==csum)
     51                 {
     52                     cnum=min(cnum,val[k]);
     53                 }
     54             }
     55             d[i][j]=csum;
     56             p[i][j]=cnum;
     57         }
     58     }
     59 }
     60 
     61 inline void read()
     62 {
     63     scanf("%d%d",&n,&m);
     64     for(int i=1;i<=n;i++)
     65     {
     66         scanf("%d",&val[i]);
     67         a[i]=val[i];
     68     }
     69     sort(a+1,a+1+n);
     70     int num=unique(a+1,a+1+n)-a-1;
     71     for(int i=1;i<=n;i++)
     72         val[i]=lower_bound(a+1,a+1+num,val[i])-a;
     73     for(int i=1;i<=n;i++) cs[val[i]]++;
     74     for(int i=1;i<=num;i++) sum[i]=sum[i-1]+cs[i];
     75     for(int i=1;i<=num;i++) lt[i]=sum[i-1]+1,rt[i]=sum[i-1];
     76     for(int i=1;i<=n;i++) ef[++rt[val[i]]]=i;
     77     
     78     getblock();
     79 }
     80 
     81 inline int force(int x,int y)
     82 {
     83     for(int i=x;i<=y;i++) cs[val[i]]=0;
     84     int cnum,csum=0;
     85     for(int i=x;i<=y;i++)
     86     {
     87         cs[val[i]]++;
     88         if(cs[val[i]]>csum)
     89         {
     90             csum=cs[val[i]];
     91             cnum=val[i];
     92         }
     93         else if(cs[val[i]]==csum)
     94         {
     95             cnum=min(cnum,val[i]);
     96         }
     97     }
     98     return cnum;
     99 }
    100 
    101 inline int getsum(int ll,int rr,int x)
    102 {
    103     return upper_bound(ef+rt[x-1]+1,ef+rt[x]+1,rr)-lower_bound(ef+rt[x-1]+1,ef+rt[x]+1,ll);
    104 }
    105 
    106 
    107 inline int query(int x,int y)
    108 {
    109     bx=x/sz+(x%sz!=0);
    110     by=y/sz+(y%sz!=0);
    111     if(bx==by||bx+1==by) return force(x,y);
    112     
    113     int h=0;
    114     for(int i=x;i<=ed[bx];i++) cs[val[i]]=0;
    115     for(int i=st[by];i<=y;i++) cs[val[i]]=0;
    116     for(int i=x;i<=ed[bx];i++)
    117     {
    118         cs[val[i]]++;
    119         if(cs[val[i]]==1) q[++h]=val[i];
    120     }
    121     for(int i=st[by];i<=y;i++)
    122     {
    123         cs[val[i]]++;
    124         if(cs[val[i]]==1) q[++h]=val[i];
    125     }
    126     bx++; by--;
    127     int res=d[bx][by],ans=p[bx][by];
    128     for(int i=1;i<=h;i++)
    129     {
    130         int bnt=getsum(q[i]);
    131         if(bnt+cs[q[i]]>res)
    132         {
    133             ans=q[i];
    134             res=bnt+cs[q[i]];
    135         }
    136         else if(bnt+cs[q[i]]==res)
    137         {
    138             ans=min(ans,q[i]);
    139         }
    140     }
    141     return ans;
    142 }
    143 
    144 inline void go()
    145 {
    146     int x,y,ans=0;
    147     while(m--)
    148     {
    149         scanf("%d%d",&x,&y);
    150         x=(x+ans-1)%n+1; y=(y+ans-1)%n+1;
    151         if(x>y) swap(x,y);
    152         ans=a[query(x,y)];
    153         printf("%d\n",ans); 
    154     }
    155 }
    156 
    157 int main()
    158 {
    159     read();
    160     go();
    161     return 0;
    162 }

    再一次被二分干掉了。。。

  • 相关阅读:
    SpringBoot集成RocketMQ报错:Bad annotation definition in @ExtRocketMQTemplateConfiguration...
    RocketMQ分析
    SpringBoot 自定义 health Actuator 原理
    【质量】容错机制
    【Java】ByteBuffer介绍
    【AWS】Essentials
    【QA123】NFR 非功能性需求
    【JVM123】OOM分析和解决
    【网络123】Http返回码
    【网络123】HTTP连接
  • 原文地址:https://www.cnblogs.com/proverbs/p/2865123.html
Copyright © 2011-2022 走看看