• BZOJ2724: [Violet 6]蒲公英


    n<=40000个数,在线问m<=50000次区间众数,数字Ai<=1e9。

    重要结论:$mode(a cup  b)epsilon mode(a) cup b$,显然。

    用分块做,对区间[L,R]取众数,就先对他们跨过的块O(1)取答案--预处理A(i,j)表示块i到块j的众数即可,然后对两边零散的数和他们跨过的块的那个众数都算一次在[L,R]的出现次数即可。

    现在问题就是算某个数在某个区间出现次数。

    方法一:把每个数的位置取出来二分!n*sqrt(n)*logn,慢

    方法二:前缀思想!计算[1,R]的减去[1,L-1]的,问题再次转化。然后[1,R]的某个数的出现次数,可以先预处理B(i,j)表示前i个块数j出现次数,然后C(i,j,x)表示块i前j个数中数x出现多少次,这里要在每个块里再离散化一次,D(i,j)表示数i在块j的C数组中的x是多少,因为x太大C开不下。。

    其实C和D是多余的,前后两段数直接开桶记录然后用B来算中间就行了。

     1 #include<stdio.h>
     2 #include<algorithm>
     3 #include<string.h>
     4 #include<stdlib.h>
     5 #include<math.h>
     6 //#include<bitset>
     7 //#include<iostream>
     8 using namespace std;
     9 
    10 int n,m,q;
    11 #define maxn 41011
    12 #define maxm 311
    13 int lisan[maxn],li=0,bud[maxn];
    14 int most[maxm][maxm],num[maxm],lnum,s[maxm][maxn],cnt[maxm][maxm][maxm],pos[maxn][maxm],bel[maxn],tot,a[maxn];
    15 
    16 int calc(int p,int v) {if (!p) return 0;return s[bel[p]-1][v]+cnt[bel[p]][p-(bel[p]-1)*m][pos[v][bel[p]]];}
    17 int main()
    18 {
    19     scanf("%d%d",&n,&q);
    20     m=(int)sqrt(n);
    21     for (int i=1;i<=n;i++) bel[i]=(i-1)/m+1;
    22     tot=bel[n];
    23     for (int i=1;i<=n;i++) scanf("%d",&a[i]),lisan[++li]=a[i];
    24     sort(lisan+1,lisan+1+li); li=unique(lisan+1,lisan+1+li)-lisan-1;
    25     for (int i=1;i<=n;i++) a[i]=lower_bound(lisan+1,lisan+1+li,a[i])-lisan;
    26     for (int i=1,now=1;i<=n;i+=m,now++)
    27     {
    28         memset(bud,0,sizeof(bud));
    29         int Max=0;
    30         for (int j=i;j<=n;j++)
    31         {
    32             bud[a[j]]++;
    33             if (bud[a[j]]>bud[Max] || (bud[a[j]]==bud[Max] && a[j]<Max)) Max=a[j];
    34             if (bel[j]!=bel[j+1]) most[now][bel[j]]=Max;
    35         }
    36     }
    37     for (int i=1,now=1;i<=n;i+=m,now++)
    38     {
    39         lnum=0;
    40         for (int j=i;bel[j]==bel[i];j++) num[++lnum]=a[j];
    41         sort(num+1,num+1+lnum); lnum=unique(num+1,num+1+lnum)-num-1;
    42         for (int j=i;bel[j]==bel[i];j++)
    43         {
    44             for (int k=i;k<j;k++) cnt[now][j-i+1][pos[a[k]][now]]=cnt[now][j-i][pos[a[k]][now]];
    45             pos[a[j]][now]=lower_bound(num+1,num+1+lnum,a[j])-num,
    46             cnt[now][j-i+1][pos[a[j]][now]]++;
    47         }
    48         for (int j=1,r=min(now*m,n)-(now-1)*m;j<=li;j++)
    49             s[now][j]=s[now-1][j]+cnt[now][r][pos[j][now]];
    50     }
    51     int x,y,last=0;
    52     memset(bud,0,sizeof(bud));
    53     while (q--)
    54     {
    55         scanf("%d%d",&x,&y);
    56         x=(x+last-1)%n+1,y=(y+last-1)%n+1;
    57         if (x>y) {int t=x;x=y;y=t;}
    58         if (bel[x]==bel[y])
    59         {
    60             int Max=0;
    61             for (int i=x;i<=y;i++)
    62             {
    63                 bud[a[i]]++;
    64                 if (bud[a[i]]>bud[Max] || (bud[a[i]]==bud[Max] && a[i]<Max)) Max=a[i];
    65             }
    66             printf("%d
    ",(last=lisan[Max]));
    67             for (int i=x;i<=y;i++) bud[a[i]]--;
    68         }
    69         else
    70         {
    71             int Max=most[bel[x]+1][bel[y]-1],tot=calc(y,Max)-calc(x-1,Max);
    72             for (int j=x,tmp;bel[j]==bel[x];j++)
    73             {
    74                 tmp=calc(y,a[j])-calc(x-1,a[j]);
    75                 if (tmp>tot || (tmp==tot && a[j]<Max)) Max=a[j],tot=tmp;
    76             }
    77             for (int j=y,tmp;bel[j]==bel[y];j--)
    78             {
    79                 tmp=calc(y,a[j])-calc(x-1,a[j]);
    80                 if (tmp>tot || (tmp==tot && a[j]<Max)) Max=a[j],tot=tmp;
    81             }
    82             printf("%d
    ",(last=lisan[Max]));
    83         }
    84     }
    85     return 0;
    86 }
    View Code
  • 相关阅读:
    图片预加载的JS代码
    JavaScript实现漫天飞花及文字滚动特效的代码
    判断远程图片是否存在的JavaScript代码
    dos批处理命令详解
    内存虚拟盘软件XMSDSK的使用
    医学论坛(收集)
    velocity
    java开源项目 源代码
    开放源代码的全文检索引擎Lucene
    批处理命令大全
  • 原文地址:https://www.cnblogs.com/Blue233333/p/8035085.html
Copyright © 2020-2023  润新知