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