zoukankan      html  css  js  c++  java
  • UVA 11235 Frequent values (RMQ)

    题意:给一个非降序排列的整数数组a,你的任务是对于一系列询问(i, j)。回答ai,ai+1...aj中次数出现最多的值所出现的次数。

    思路:因为数列是非降序的,所以全部相等的数都会聚集在一起。这样我们就能够把整个数组进行编码。如-1,1,1,2,2,2,4就能够编码成(-1,1),(1,2),(2,3),(4,1)表示(a,b)数组中的a连续出现了b次。用num[i]表示原数组下表是i的数在编码后的第num[i]段。

    left[i],right[i]表示第i段的左边界和右边界。用coun[i]表示第i段有conu[i]个同样的数。这种话每次查询(L, R)就仅仅要计算(right[L]-L+1),(R-left[R]+1)和RMQ(num[L]+1, num[R]-1)这三个值的最大值就能够了。


    当中,RMQ是对coun数组进行取件查询的结果。


    特殊的,假设L和R在同一个区间内的话。那么结果就是(R-L+1)

    AC代码:

    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    
    typedef long long LL;
    const int MAXN = 100005;
    const int MAXM = 100005;
    const double eps = 1e-12;
    
    int num[MAXN], coun[MAXN], Left[MAXN], Right[MAXN];
    int n, q, a, last, tot;
    int DP[MAXN][20];
    
    void init_RMQ()
    {
        memset(DP,0,sizeof(DP));
        for(int i=1;i<=tot;i++) DP[i][0] = coun[i];
        for(int j=1;(1<<j)<=n;j++)
        {
            for(int i=1;i+(1<<j)<=tot;i++)
            {
                DP[i][j] = max(DP[i][j-1], DP[i+(1<<(j-1))][j-1]);
            }
        }
    }
    
    int RMQ(int L, int R)
    {
        if(L > R) return 0;
        int k = 0;
        while((1<<(1+k)) <= R-L+1) k++;
        return max(DP[L][k], DP[R-(1<<k)+1][k]);
    }
    
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("in.cpp","r",stdin);
        freopen("out.cpp","w",stdout);
        #endif // ONLINE_JUDGE
        while(~scanf("%d", &n) && n)
        {
            scanf("%d", &q);
            tot = 0;
            memset(Left,0,sizeof(Left));
            memset(Right,0,sizeof(Right));
            memset(coun,0,sizeof(coun));
            for(int i=1;i<=n;i++)
            {
                scanf("%d", &a);
                if(i==1)
                {
                    ++tot;
                    last=a;
                    Left[tot] = 1;
                }
                if(last == a)
                {
                    num[i]=tot;
                    coun[tot]++;
                    Right[tot]++;
                }
                else
                {
                    num[i]=++tot;
                    coun[tot]++;
                    Left[tot]=Right[tot]=i;
                    last=a;
                }
            }
            init_RMQ();
            int l, r;
            for(int i=0;i<q;i++)
            {
                scanf("%d%d", &l, &r);
                if(num[l] == num[r]) { printf("%d
    ", r-l+1);  continue; }
                printf("%d
    ", max( RMQ(num[l]+1, num[r]-1), max( Right[num[l]]-l+1, r-Left[num[r]]+1 ) ) );
            }
        }
        return 0;
    }
    


  • 相关阅读:
    How To Upgrade ASM from 10.2 to 11.1 (RAC)
    Moving ASM spfile to a shared device in RAC
    关于2019夏季小学期收获与感想
    大道至简读后感
    关于2017届学长制作分享软件share(失物招领)的使用体验和需改进的内容
    暑假周报告总结第三周
    暑假周报告总结第二周
    假期周进度报告第一周
    成功试验基于C#/.NET的Android开发
    基于Linux命令行终端的ftp客户端程序
  • 原文地址:https://www.cnblogs.com/gavanwanggw/p/7059963.html
Copyright © 2011-2022 走看看