HDU1806 Frequent values

题解:

注意数组a是非降序排列。

所以将a数组转化出现次数的数组b

例如 -1 -1 2 3 对应 2 2 1 1

那么每次查询,分为左边,右边和中间三部分,

预处理每个数对应的左右范围.可以用map,也可以用二分。

代码:

//二分处理
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<map>
#include<set>
#include<vector>
using namespace std;
using namespace std;
#define pb push_back
#define mp make_pair
#define se second
#define fs first
#define ll long long
#define MS(x,y) memset(x,y,sizeof(x))
#define MC(x,y) memcpy(x,y,sizeof(x))
#define ls o<<1
#define rs o<<1|1
#define SZ(x) ((int)(x).size())
#define FOR(it,c) for(__typeof((c).begin()) it=(c).begin();it!=(c).end();it++)
typedef pair<int,int> P;
const double eps=1e-9;
const int maxn=100100;
const int N=1e9;
const int mod=1e9+7;

ll read()
{
    ll x=0,f=1;char ch=getchar();
    while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
//-----------------------------------------------------------------------------

int a[maxn],b[maxn],mx[maxn][20];
int n,m,k,l,r;
map<int,int> Num;

void rmq_init()
{
    for(int i=1;i<=n;i++) mx[i][0]=b[i];
    k=(int)(log(n*1.0)/log(2.0));
    for(int i=1;i<=k;i++)
    for(int j=1;j<=n;j++){
        mx[j][i]=mx[j][i-1];
        if(j+(1<<(i-1))<=n) mx[j][i]=max(mx[j][i],mx[j+(1<<(i-1))][i-1]);
    }
}

int rmq_max(int l,int r)
{
    k=(int)(log((r-l+1.0)*1.0)/log(2.0));
    return max(mx[l][k],mx[r-(1<<k)+1][k]);
}

int bs_left(int l)
{
    int L=1,R=l,Goal=l;
    while(L<=R){
        int M=(L+R)>>1;
        if(a[M]==a[l]){
            Goal=M;
            R=M-1;
        }
        else L=M+1;
    }
    return Goal;
}

int bs_right(int r)
{
    int L=r,R=n,Goal=r;
    while(L<=R){
        int M=(L+R)>>1;
        if(a[M]==a[r]){
            Goal=M;
            L=M+1;
        }
        else R=M-1;
    }
    return Goal;
}

int main(){
    while(scanf("%d",&n)&&n){
        scanf("%d",&m);
        Num.clear();
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            Num[a[i]]++;
        }
        for(int i=1;i<=n;i++) b[i]=Num[a[i]];
        rmq_init();
        for(int i=1;i<=m;i++){
            scanf("%d%d",&l,&r);
            if(a[l]==a[r]) printf("%d\n",r-l+1);
            else{
                int L_max=bs_right(l)-l+1;
                int R_max=r-bs_left(r)+1;
                int M_max=0;
                if(bs_right(l)+1<=bs_left(r)-1) M_max=rmq_max(bs_right(l)+1,bs_left(r)-1);
                printf("%d\n",max(max(L_max,R_max),M_max));
            }
        }
    }
    return 0;
}
时间: 2024-12-18 02:43:41

HDU1806 Frequent values的相关文章

uva11235(Frequent values)(HDU1806)

题目地址:Frequent values 题目大意.解题思路:  见白皮书p198. 代码: 1 #include <stdio.h> 2 #include <string.h> 3 #include <math.h> 4 #include <algorithm> 5 #include <vector> 6 using namespace std; 7 const int M=100100; 8 int a[M]; 9 int val[M],cn

POJ 3368:Frequent values RMQ

Frequent values 题目链接: http://poj.org/problem?id=3368 题意: 给出一个非递减序列,求区间内最多的数字的数量 题解: 水题,dp[i][j]记录从 i 开始2^j个数中的出现最多的数,合并dp[i][j]和dp[i+(1<<j)][j]得到dp[i][1<<(j+1)]的时候,由于序列是连续的,只要多考虑一个i+(1<<j)-1(即dp[i][j]所能到达的最右端)上得数字在区间内出现的次数就好了. 代码 #includ

uva 11235 - Frequent values(RMQ)

题目链接:uva 11235 - Frequent values 题目大意:给定一个非降序的整数数组,要求计算对于一些询问(i,j),回答ai,ai+1,-,aj中出现最多的数出现的次数. 解题思路:因为序列为非降序的,所以相同的数字肯定是靠在一起的,所以用o(n)的方法处理处每段相同数字的区间.然后对于每次询问: num[i]=num[j]:j?i+1 numi≠numj:max(RMQ(righti+1,reftj?1),max(righti?i+1,j?leftj+1)) #include

poj 3368 Frequent values(线段树解法)

题目链接:http://poj.org/problem?id=3368 题目大意:给你一段不下降的序列,求给定区间里出现次数最多的那个数字的次数. 思路:首先看到这题时,第一感觉线段树,但是仔细一看问题来啦,用线段数我怎么才能计算出某段区间里出现的那个数,因为出现最多的那个数可能不是在他它的左儿子上也不是在它的右儿子上,可能在当他们合并成一个区间时就出现啦,但是这儿我们需要注意的就是,题目给的是一段不下降的序列,那么突破口就出来啦,因为如果出现相同的数字,那么它们一定是连续的.所以我们只需要在普

POJ3368 Frequent values 线段树

N个数为非递减顺序,给定范围l,r,求[l,r]区间内数字出现频率最高的次数. 可以用线段树来做.先说查询,我们设节点P对应的区间为[a, b],左孩子节点为p1,右孩子节点为p2,那么 P也许不等于 max(p1 , p2),原因是如果p1中频率较低的某个数与p2中出现频率较低的某个数是同一个数,并且两者出现次数加起来大于max(p1, p2),但是,题目说N个数为非递减顺序排列,所以这个可能只会发生在p1的右端和p2的左端对应的数是同一个数,因此,我们还要处理这第三个可能. 查询的问题解决,

POJ 3368 Frequent values

Frequent values Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 13051 Accepted: 4792 Description You are given a sequence of n integers a1 , a2 , ... , an in non-decreasing order. In addition to that, you are given several queries consisti

POJ 3368 Frequent values RMQ ST算法/线段树

                                                     Frequent values Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 15229   Accepted: 5550 Description You are given a sequence of n integers a1 , a2 , ... , an in non-decreasing order. In

poj 3368 Frequent values 解题报告

题目链接:http://poj.org/problem?id=3368 题目意思:给出一段 n 个数的序列你,对于区间 [l, r] 的询问,找出 出现频率最高的数的次数.考虑到序列中的数是非递减的,也就是相同的数会连续不间断地在一起,于是就才有了代码中这个部分来预判了: if (s > t)        printf("%d\n", ans); 这个人写RMQ 写得不错:http://dongxicheng.org/structure/lca-rmq/ 这题就是套模板的,纪念

UVA 11235 Frequent values

1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 6 const int maxn=100005; 7 8 int count[maxn]; 9 int num[maxn],ll[maxn],rr[maxn]; 10 int tot; 11 int d[maxn][50]; 12 13 int rmq (int l,int r){ 14 int