#6285. 数列分块入门 9(区间的最小众数 离散化+数列分块)

题目链接:https://loj.ac/problem/6285

题目大意:中文题目

论文链接:

 https://wenku.baidu.com/view/99bf0fc78662caaedd3383c4bb4cf7ec4afeb628.html 

具体思路:dp[i][j]表示第i块到第j块的的众数是谁,然后每一次询问先询问两旁不完整的块,然后中间的整块o(1)询问就可以了。

AC代码:

 1 #include<iostream>
 2 #include<stack>
 3 #include<stdio.h>
 4 #include<cmath>
 5 #include<vector>
 6 #include<string>
 7 #include<cstring>
 8 #include<algorithm>
 9 using namespace std;
10 # define ll long long
11 const int maxn = 2e5+100;
12 vector<int>q[maxn];
13 vector<int>vis;
14 int belong[maxn],a[maxn];
15 int num[maxn];
16 int dp[2500][2500];
17 int n,block=50;
18 void init(int x){
19 memset(num,0,sizeof(num));
20 int maxx=0,ans=0;
21 for(int i=(x-1)*block+1;i<=n;i++){
22 num[a[i]]++;
23 if(num[a[i]]>maxx||(num[a[i]]==maxx&&ans>a[i])){
24 maxx=num[a[i]];
25 ans=a[i];
26 }
27 dp[x][belong[i]]=ans;
28 }
29 }
30 int cal(int st,int ed,int num){//返回的是下标,所以对于结尾是upper,对于开始是lower
31 return upper_bound(q[num].begin(),q[num].end(),ed)-lower_bound(q[num].begin(),q[num].end(),st);
32 }
33 int  ask(int st,int ed){
34 int maxx=0,ans=0;
35 if(belong[st]==belong[ed]){
36 for(int i=st;i<=ed;i++){
37 int tmp=cal(st,ed,a[i]);
38 if(maxx<tmp||(maxx==tmp&&ans>a[i])){
39 ans=a[i];
40 maxx=tmp;
41 }
42 }
43 return ans;
44 }
45 for(int i=st;i<=min(ed,(belong[st]*block));i++){
46 int tmp=cal(st,ed,a[i]);
47 if(maxx<tmp||(maxx==tmp&&ans>a[i])){
48 ans=a[i];
49 maxx=tmp;
50 }
51 }
52 for(int i=(belong[ed]-1)*block+1;i<=ed;i++){
53 int tmp=cal(st,ed,a[i]);
54 if(maxx<tmp||(maxx==tmp&&ans>a[i])){
55 ans=a[i];
56 maxx=tmp;
57 }
58 }
59 int tmp=cal(st,ed,dp[belong[st]+1][belong[ed]-1]);
60 if(maxx<tmp||(maxx==tmp&&ans>dp[belong[st]+1][belong[ed]-1])){
61 ans=dp[belong[st]+1][belong[ed]-1];
62 maxx=tmp;
63 }
64 return ans;
65 }
66 int main(){
67 scanf("%d",&n);
68 for(int i=1;i<=n;i++){
69 scanf("%d",&a[i]);
70 vis.push_back(a[i]);
71 belong[i]=(i-1)/block+1;
72 }
73 sort(vis.begin(),vis.end());
74 vis.erase(unique(vis.begin(),vis.end()),vis.end());//离散化
75 for(int i=1;i<=n;i++){
76 a[i]=lower_bound(vis.begin(),vis.end(),a[i])-vis.begin();
77 }
78 for(int i=1;i<=belong[n];i++){
79 init(i);//求dp[i][j]
80 }
81 for(int i=1;i<=n;i++){
82 q[a[i]].push_back(i);
83 }
84 int Case=n,st,ed;
85 while(Case--){
86 scanf("%d %d",&st,&ed);
87 printf("%d
",vis[ask(st,ed)]);
88 }
89 return 0;
90 }
原文地址:https://www.cnblogs.com/letlifestop/p/10478654.html