• #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 }
  • 相关阅读:
    asp.net textbox 控件如何清除缓存
    extjs Accordion 怎样把展开符号:加号(+)放在左边?
    ORACLE 调试输出,字符串执行函数
    Oracle中table函数的应用
    Oracle LAST_DAY(d)
    Oracle 管道化表函数(Pipelined Table)[转载]
    ext中fieldLabel文本太宽的问题,以及Panel居中显示
    什么是泛型(C#)
    设置Ext tab的宽度自动适应
    js选择日期即时把两个日期相差天数显示出来?
  • 原文地址:https://www.cnblogs.com/letlifestop/p/10478654.html
Copyright © 2020-2023  润新知