#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\n",vis[ask(st,ed)]); 88 } 89 return 0; 90 }