分块入门9 --- 区间众数

Posted xxrll

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了分块入门9 --- 区间众数相关的知识,希望对你有一定的参考价值。

??‍????‍????‍♀?

//写完入门后,这道一直想补,终于拖到了现在d=====( ̄▽ ̄*)b

分块维护每一块的众数(第i块到第j块的众数),所以中间的块预处理就可以得到,旁边的块我们暴力枚举,但这样前面预处理得到的还需要统计它出现次数。这个我们就可以用到二分来找,找中间块最多的那个数,二分找在[x,y]内出现次数,所以我们就需要一个数组来保存某个数所有的出现位置,边界块的每一个数也可以这样找,然后比较更新。这里因为要经常用到a[i]即读入的某个数,但它的大小不是连续的,为了防t也为了满足题目中次数相同取先出现的条件,我们就可以把它标号为出现次序(id),然后再来一个数组专门根据保存它原来的值,a[i]就专门保存它的id,还要思考如何判断a[i]已经编过次序,我们就用map来,其他是用id来做下标,而map就是用a[i]原本的值。

tips: ①用lld(一把辛酸泪┭┮﹏┭┮)

  ②这道题来说好像数据蛮水?所以用scanf就行,和read()时间差不多。

  ③不能像平时一样blo=sqrt(n),会超时,所以自己手动定一个,比如80,150就会t了,应该是两边处理时的原因(也许...)

       ④ 用cin的话,前面加上ios::sync_with_stdio(false);cin.tie(0); 虽然还是会慢一点(500ms上下),但是也不会超。

技术图片
  1 #include<bits/stdc++.h>
  2 #include<iostream>
  3 #include<stack>
  4 #include<algorithm>
  5 #include<cstdio>
  6 #include<cmath>
  7 #include<cstring>
  8 #define mem(a) memset(a,0,sizeof(a))
  9 #define mem1(a) memset(a,-1,sizeof(a))
 10 #define fio ios::sync_with_stdio(false);cin.tie(0)
 11 #define ll long long
 12 //#define mp make_pair
 13 #define inf 0x3f3f3f3f
 14 const int N=1e5+5;
 15 const int M=1e4+10;
 16 const int mod=9973;
 17 using namespace std;
 18 int blo,num,belong[N],n,cnt[N],r[N],l[N];
 19 ll a[N],k,pmx[M][M],d[N],id;
 20 vector<int>ve[N];
 21 map<int,int>mp;
 22 inline ll read()
 23 
 24     ll sum=0,f=1;
 25     char c=getchar();
 26     while(c>9||c<0) if(c==-) f=-f; c=getchar();
 27     while(c>=0&&c<=9) sum=sum*10+c-0, c=getchar();
 28     return sum*f;
 29 
 30 inline void prework(int now)
 31 
 32     mem(cnt);
 33     int mx=0,ans=0;
 34     for(int i=l[now];i<=n;i++)
 35     
 36         cnt[a[i]]++;
 37         if(cnt[a[i]]>mx || (cnt[a[i]]==mx && d[a[i]]<d[ans]))
 38         
 39             mx=cnt[a[i]];
 40             ans=a[i];
 41         
 42         pmx[now][belong[i]]=ans;
 43     
 44 
 45 inline void build()
 46 
 47     blo=80; //
 48     num=(n%blo)? n/blo+1:n/blo;
 49     for(int i=1;i<=n;i++)
 50     
 51         belong[i]=(i-1)/blo+1;
 52     
 53     for(int i=1;i<=num;i++)
 54     
 55         l[i]=(i-1)*blo+1;
 56         r[i]=i*blo;
 57     
 58     r[num]=n;
 59     for(int i=1;i<=num;i++)
 60         prework(i);
 61 
 62 inline ll binarys(int now,int x,int y)
 63 
 64     return upper_bound(ve[now].begin(),ve[now].end(),y)-lower_bound(ve[now].begin(),ve[now].end(),x);
 65 
 66 inline ll query(int x,int y)
 67 
 68     ll ans=pmx[belong[x]+1][belong[y]-1],mx=binarys(ans,x,y);
 69     for(int i=x;i<=min(y,r[belong[x]]);i++)
 70     
 71          ll t=binarys(a[i],x,y);
 72          if(t>mx || (t==mx && d[a[i]]<d[ans]))
 73          
 74              ans=a[i];
 75              mx=t;
 76          
 77     
 78     if(belong[x]!=belong[y])
 79     
 80         for(int i=l[belong[y]];i<=y;i++)
 81         
 82              ll t=binarys(a[i],x,y);
 83              if(t>mx || (t==mx && d[a[i]]<d[ans]))
 84              
 85                 ans=a[i];
 86                 mx=t;
 87              
 88         
 89     
 90     return ans;
 91 
 92 int main()
 93 
 94     scanf("%d",&n);
 95     //n=read();
 96     for(int i=1;i<=n;i++)
 97     
 98         scanf("%lld",&a[i]);
 99          //a[i]=read();
100         if(!mp[a[i]])
101         
102             mp[a[i]]=++id;
103             d[id]=a[i];
104         
105         a[i]=mp[a[i]];
106         ve[a[i]].push_back(i);
107     
108     build();
109     int x,y;
110     for(int i=1;i<=n;i++)
111     
112          scanf("%d%d",&x,&y);
113          //x=read(),y=read();
114          printf("%lld\n",d[query(x,y)]);
115     
116     return 0;
117 
o(* ̄▽ ̄*)o

 

以上是关于分块入门9 --- 区间众数的主要内容,如果未能解决你的问题,请参考以下文章

区间众数(分块)

[Luogu P4168] [Violet]蒲公英 (分块)

数列分块入门 9 & 蒲公英

数列分块入门 9 & 蒲公英

loj#6285 数列分块入门 9 ( 回 滚 )

arcpy-字段唯一值重复值最值平均值方差标准差中数众数