Frequent values UVA - 11235(巧妙地RMQ)

题意:

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

解析:

白书p198

  

  

  其实意思就是把每个值转换为次数 因为相等的值又是连续的  然后标记每个值的下标所对应的次数数组中的下标  rmq求区间次数的最大值

  因为不易更新,所以把left和right中的R和L啥的变为其对应的次数段  即num[L]  num[R ]

  

#include <iostream>
#include <cstdio>
#include <sstream>
#include <cstring>
#include <map>
#include <set>
#include <vector>
#include <stack>
#include <queue>
#include <algorithm>
#include <cmath>
#define rap(i, a, n) for(int i=a; i<=n; i++)
#define rep(i, a, n) for(int i=a, i<n; i++)
#define lap(i, a, n) for(int i=n; i>=a; i--)
#define lep(i, a, n) for(int i=n; i>a; i--)
#define MOD 2018
#define LL long long
#define ULL unsigned long long
#define Pair pair<int, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define _  ios_base::sync_with_stdio(0),cin.tie(0)
//freopen("1.txt", "r", stdin);
using namespace std;
const int maxn = 101000, INF = 0x7fffffff;
int d[maxn][50], lef[maxn], righ[maxn], num[maxn], val[maxn], cnt[maxn], a[maxn];
int n, q, len;

void RMQ_init()
{
    rap(i, 1, len) d[i][0] = cnt[i];
    for(int j=1; (1<<j) <= len+1; j++)
        for(int i=1; i+(1<<j)-1 <= len; i++)
            d[i][j] = max(d[i][j-1],d[i+(1<<(j-1))][j-1]);
}

int RMQ(int l, int r)
{
    int k = 0;
    while(1<<(k+1) <= r-l+1) k++;
    return max(d[l][k], d[r-(1<<k)+1][k]);
}


int main()
{
    while(~scanf("%d", &n) && n)
    {
        scanf("%d", &q);
        len = 1;
        mem(cnt, 0);
        scanf("%d", &a[1]);
        val[len] = a[1];    //标记位置为次数是哪一个数的
        cnt[len] = 1;       //统计位置为len的次数
        num[1] = len;       //原数组下标对应在次数数组的哪一个下标
        lef[1] = 1;        //lef[i]代表次数数组中下标为len的次数在原数组中  连续区间的左端点值的下标(因为每个相等的元素是连续的)
        rap(i, 2, n)
        {
            scanf("%d", &a[i]);
            if(a[i] == a[i-1])
            {
                cnt[len]++;
                num[i] = len;
            }
            else
            {
                righ[len] = i-1;
                len++;
                val[len] = a[i];
                cnt[len] = 1;
                num[i] = len;
                lef[len] = i;
            }
        }
        RMQ_init();
        int l, r;
        while(q--)
        {
            scanf("%d%d", &l, &r);
            if(num[l] == num[r])
                printf("%d\n", r-l+1);
            else
            {
                int ans = 0;
                if(num[l]+1<=num[r]-1)
                    ans=RMQ(num[l]+1,num[r]-1);
                ans = max(ans,max(righ[num[l]]-l+1,r-lef[num[r]]+1));
                printf("%d\n", ans);
            }

        }
    }

    return 0;
}

  

猜你喜欢

转载自www.cnblogs.com/WTSRUVF/p/9441980.html