• UVA 11235 (RMQ) 频繁出现的数值


    题目大意是给出一个非降序排列的数组,然后n个询问,每次询问一个区间内出现次数最多的数的次数。

    首先要弄清楚题目的是一个非降序的数组,那么说明相等的数都会在一起,类似于11223334569这样的,那么可以将其合并,由于这种多次区间询问的题一般用

    到的是线段树或者RMQ,所以就往这方面去靠,用num[i]和cont[i]表示第i段的数值和出现的次数,val[i]表示位置i所在段的编号,lef[i]和ri[i]表示位置i所在段的左右端点

    位置,那么对于每次查询(l,r)区间就分成了三段,ri[l]-l+1,r-lef[r]+1和中间一段,而中间的一段就完全是根据cont数组求的RMQ问题,然后三者取大的就好。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 #include<algorithm>
     5 using namespace std;
     6 
     7 const int M = 1e5 + 10;
     8 int a[M],d[M][20],cont[M],num[M];
     9 int lef[M],ri[M],val[M];
    10 int max(int x,int y) {return x>y?x:y;}
    11 
    12 void rmq(int x)
    13 {
    14     for (int i=1 ; i<=x ; i++) d[i][0]=cont[i];
    15     for (int j=1 ; (1<<j)<=x ; j++)
    16         for (int i=0 ; i+(1<<j)-1<x ; i++)
    17            d[i][j]=max(d[i][j-1],d[i+(1<<(j-1))][j-1]);
    18 }
    19 
    20 int rmq(int l,int r)
    21 {
    22     if (l>r) return 0;
    23     int k=0;
    24     while ((1<<(k+1))<=r-l+1) k++;
    25     return max(d[l][k],d[r-(1<<k)+1][k]);
    26 }
    27 
    28 int main()
    29 {
    30     int n,q,i;
    31     while (~scanf("%d",&n)&&n){
    32     scanf("%d",&q);
    33     for (i=1 ; i<=n ; i++) scanf("%d",a+i);
    34     int ans=-M,j=1;
    35     memset(cont,0,sizeof(cont));
    36     for (i=1 ; i<=n ; i++)
    37     {
    38         if (a[i]!=ans)
    39         {
    40             val[j]=a[i];
    41             ans=a[i];
    42             int k=i,w=i;
    43             while (ans==a[i]){
    44                 cont[j]++;
    45                 i++;
    46             }
    47             i--;
    48             for ( ; k<=i ; k++)
    49             {
    50                 num[k]=j;
    51                 lef[k]=w;
    52                 ri[k]=i;
    53             }
    54             j++;
    55         }
    56     }
    57     j--;
    58     rmq(j);
    59     int l,r;
    60    /* for (i=1 ; i<=j ; i++) cout<<val[i]<<" ";
    61     cout<<endl;
    62     for (i=1 ; i<=j ; i++) cout<<cont[i]<<" ";
    63     cout<<endl;
    64     for (i=1 ; i<=n ; i++) cout<<num[i]<<" ";
    65     cout<<endl;
    66     for (i=1 ; i<=n ; i++) cout<<lef[i]<<" ";
    67     cout<<endl;
    68     for (i=1 ; i<=n ; i++) cout<<ri[i]<<" ";
    69     cout<<endl;*/
    70     while (q--)
    71     {
    72         scanf("%d%d",&l,&r);
    73         if (num[l]==num[r])
    74         {
    75             printf("%d
    ",r-l+1);
    76             continue;
    77         }
    78         printf("%d
    ",max(r-lef[r]+1,max(rmq(num[ri[l]+1],num[lef[r]-1]),ri[l]-l+1)));
    79 
    80     }
    81     }
    82     return 0;
    83 }

     

  • 相关阅读:
    回首2016,展望2017
    认识多线程
    对CloseHandle用法的理解
    CDC、HDC、pDC之间的关系
    兼容位图和兼容DC的理解
    窗口中显示bmp图片的过程
    创建一个bmp格式的简单方法
    说明为什么Button控件不能使用CustomDraw技术
    MFC自绘Button按钮分析和实现
    VC之美化界面篇
  • 原文地址:https://www.cnblogs.com/JJCHEHEDA/p/5435360.html
Copyright © 2020-2023  润新知