洛谷 P4168 [Violet]蒲公英(分块)

传送门


解题思路

一言一概之,动态求区间众数。

瞄一眼数据范围,大约n根号n——分块大法好!

先把读入的数据离散化,然后进行分块处理。

对于每一个询问,把它分成整块和零散快处理:

  • 整块:预处理i到j块的众数,直接O(1)询问。
  • 零散快:预处理从1到n每个数出现的位置,枚举零散快的数字,二分查找询问的区间内的个数,与整块的众数作比较。

预处理众数:枚举起始块,向右暴力枚举,O(n*块数)

预处理数字位置:扫一遍,加入vector中即可

假设块数为T,则时间复杂度为O(n*T+m*n/T*log(n)),所以当n*T=m*n/T*log(n)时,和最小,所以T=sqrt(m*logn)。

按照sqrt(n)也能水过去

AC代码

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cmath>
 4 #include<cstdio>
 5 #include<cstring>
 6 #include<cstdlib>
 7 #include<queue>
 8 #include<set>
 9 #include<map>
10 #include<vector>
11 #include<iomanip>
12 #include<ctime>
13 #include<stack>
14 using namespace std;
15 const int maxn=40005;
16 vector<int> v[maxn];
17 int n,m,sq,a[maxn],aa[maxn],q[maxn],cnt,now=1,l[maxn],r[maxn],id[maxn],c[maxn],mode[1005][1005]; 
18 int ll,rr,anss;
19 int main()
20 {
21     cin>>n>>m;
22     sq=sqrt(m);
23     if(sq*sq<m) sq++;
24     for(int i=1;i<=n;i++) {
25         scanf("%d",&aa[i]);
26         q[i]=aa[i];
27     }
28     sort(q+1,q+n+1);
29     int len=unique(q+1,q+n+1)-q-1;
30     for(int i=1;i<=n;i++) a[i]=lower_bound(q+1,q+len+1,aa[i])-q;
31     l[now]=1;
32     for(int i=1;i<=n;i++){
33         if(cnt==sq){
34             r[now++]=i-1;
35             l[now]=i;
36             cnt=0;
37         }
38         cnt++;
39         id[i]=now;
40     }
41     r[now]=n;
42     for(int i=1;i<=sq;i++){
43         memset(c,0,sizeof(c));
44         int maxx=0;
45         for(int j=i;j<=sq;j++){
46             for(int k=l[j];k<=r[j];k++){
47                 c[a[k]]++;
48                 if((c[a[k]]>c[maxx])||(c[a[k]]==c[maxx]&&a[k]<maxx)) maxx=a[k];
49             }
50             mode[i][j]=maxx;
51         }
52     }
53     for(int i=1;i<=n;i++) v[a[i]].push_back(i);
54     int ans=0;
55     for(int i=1;i<=m;i++){
56         anss=0; 
57         scanf("%d%d",&ll,&rr);
58         ll=(ll+q[ans]-1)%n+1;
59         rr=(rr+q[ans]-1)%n+1;
60         if(ll>rr) swap(ll,rr);
61         if(id[ll]==id[rr]){
62             for(int j=ll;j<=rr;j++){
63                 int noww=upper_bound(v[a[j]].begin(),v[a[j]].end(),rr)-lower_bound(v[a[j]].begin(),v[a[j]].end(),ll);
64                 if((noww>anss)||(noww==anss&&a[j]<ans)) ans=a[j],anss=noww;
65             }
66         }else{
67             int noww=0;
68             if(id[ll]!=id[rr]-1){
69                 ans=mode[id[ll]+1][id[rr]-1];
70                 anss=upper_bound(v[ans].begin(),v[ans].end(),rr)-lower_bound(v[ans].begin(),v[ans].end(),ll);
71             }
72             for(int j=ll;j<=r[id[ll]];j++){
73                 noww=upper_bound(v[a[j]].begin(),v[a[j]].end(),rr)-lower_bound(v[a[j]].begin(),v[a[j]].end(),ll);
74                 if((noww>anss)||(noww==anss&&a[j]<ans)) ans=a[j],anss=noww;
75             }
76             for(int j=l[id[rr]];j<=rr;j++){
77                 noww=upper_bound(v[a[j]].begin(),v[a[j]].end(),rr)-lower_bound(v[a[j]].begin(),v[a[j]].end(),ll);
78                 if((noww>anss)||(noww==anss&&a[j]<ans)) ans=a[j],anss=noww;
79             }
80         }
81         printf("%d
",q[ans]);
82     }
83     return 0;
84 }
原文地址:https://www.cnblogs.com/yinyuqin/p/14402868.html