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 addition to that, you are given several queries consisting of indices i and j (1 ≤ i ≤ j ≤ n). For each query, determine the most frequent value among the integers ai , ... , aj.

Input

The input consists of several test cases. Each test case starts with a line containing two integers n and q (1 ≤ n, q ≤ 100000). The next line contains n integers a1 , ... , an (-100000 ≤ ai ≤ 100000, for each i ∈ {1, ..., n}) separated by spaces. You can assume that for each i ∈ {1, ..., n-1}: ai ≤ ai+1. The following q lines contain one query each, consisting of two integers i and j (1 ≤ i ≤ j ≤ n), which indicate the boundary indices for the 
query.

The last test case is followed by a line containing a single 0.

Output

For each query, print one line with one integer: The number of occurrences of the most frequent value within the given range.

Sample Input

10 3
-1 -1 1 1 1 1 3 10 10 10
2 3
1 10
5 10
0

Sample Output

1
4
3

Source

题意:

给你一个非递减序列。有m次询问,每次询问区间之间出现最多的数字出现的次数。

题解:

RMQ/线段树

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<queue>
#include<cmath>
#include<map>
using namespace std ;
typedef long long ll;
#define inf 100000
inline 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;
}
//******************************************************************
struct ss{
int l,r,num,v;
}a[100001];
int counts[100001];
int dp[100001][63],n,m,p;
void rmq_init()
{
   memset(dp,0,sizeof(dp));
   for(int i=1;i<=p;i++){
    dp[i][0]=counts[i];
   }
   int k=floor(log((double)n+1)/log(2.0));
   for(int j=1;j<=k;j++)
   {
       for(int i=1;i+(1<<j)-1<=p;i++)
       {
          int oo=i+(1<<(j-1));
          dp[i][j]=max(dp[i][j-1],dp[oo][j-1]);
       }
   }
}
int RMQ(int x,int y)
{
    int oo=floor(log((double)y-x+1)/log(2.0));
    return max(dp[x][oo],dp[y-(1<<(oo))+1][oo]);
}
void work()
{
    int l,r;
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&l,&r);
        if(a[l].num==a[r].num){
            cout<<r-l+1<<endl;
        }
        else {
            int ans=a[l].r-l+1;
            ans=max(r-a[r].l+1,ans);
            l=a[l].num+1;
            r=a[r].num-1;
           if(l<=r) ans=max(ans,RMQ(l,r));
            cout<<ans<<endl;
        }
    }
}
void init()
{

    int f=0,r=0,l=0;
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i].v);
        if(f&&a[i].v!=a[i-1].v)
        {
            counts[p]=r-l+1;
            for(int j=l;j<=r;j++)
                a[j].num=p,a[j].l=l,a[j].r=r;
            r++;
            p++;
            l=r;
        }
        else if(f){
            r++;
        }
        if(f==0)
        {
            l=1;
            r=1,f=1;
            p=1;
        }

    }
    counts[p]=r-l+1;
    for(int j=l;j<=r;j++)
                a[j].num=p,a[j].l=l,a[j].r=r;
   // for(int i=1;i<=n;i++)cout<<counts[i]<<" ";
}
int main()
{

    while(scanf("%d%d",&n,&m)!=EOF)
    {
        if(n==0)break;
        init();
        rmq_init();
        work();
    }
    return 0;
}

RMQ

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<queue>
#include<cmath>
#include<map>
using namespace std ;
typedef long long ll;
#define inf 100000
inline 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;
}
//******************************************************************
struct ss
{
    int l,r,v,num;
}tr[100001*7],a[500001];
int counts[200001];
int n,m,p;
void build(int k,int s,int t)
{
    tr[k].l=s;
    tr[k].r=t;
    if(s==t){
        tr[k].v=counts[s];
        return ;
    }
    int mid=(s+t)>>1;
    build(k<<1,s,mid);
    build(k<<1|1,mid+1,t);
    tr[k].v=max(tr[k<<1].v,tr[k<<1|1].v);
}
int ask(int k,int s,int t)
{
    if(s==tr[k].l&&t==tr[k].r)
    {
        return tr[k].v;
    }
    int mid=(tr[k].l+tr[k].r)>>1;
    if(t<=mid)return ask(k<<1,s,t);
    else if(s>mid)return ask(k<<1|1,s,t);
    else {
        return max(ask(k<<1,s,mid),ask(k<<1|1,mid+1,t));
    }
}
void init()
{
    int f=0,l=0,r=0;
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i].v);
        if(f&&a[i].v!=a[i-1].v)
        {
            counts[p]=r-l+1;
            for(int j=l;j<=r;j++)a[j].l=l,a[j].r=r,a[j].num=p;

            r++;
            l=r;
            p++;
        }
        else if(f){
            r++;
        }
        if(!f)
        {
            f=l=1;
            r=p=1;
        }
    }
    counts[p]=r-l+1;
   for(int j=l;j<=r;j++)a[j].l=l,a[j].r=r,a[j].num=p;
   ///for(int i=1;i<=p;i++)cout<<counts[i]<<" ";
}
int main()
{

    while(scanf("%d%d",&n,&m)!=EOF)
    {
        p=0;
        if(n==0)break;
        init();
        build(1,1,p);
        // cout<<p<<endl;
           int x,y;
        for(int i=1;i<=m;i++)
        {

            scanf("%d%d",&x,&y);
            if(a[x].num==a[y].num){
                cout<<y-x+1<<endl;
            }
            else {
                int ans=a[x].r-x+1;
                ans=max(ans,y-a[y].l+1);
                x=a[x].num+1;
                y=a[y].num-1;
                if(x<=y)ans=max(ask(1,x,y),ans);
                cout<<ans<<endl;
            }
        }
    }
    return 0;
}

线段树

时间: 2024-10-01 04:03:48

POJ 3368 Frequent values RMQ ST算法/线段树的相关文章

poj 3368 Frequent values(RMQ)

1 /************************************************************ 2 题目: Frequent values(poj 3368) 3 链接: http://poj.org/problem?id=3368 4 题意: 给出n个数和Q个询问(l,r),对于每个询问求出(l,r)之 5 间连续出现次数最多的次数 6 算法: RMQ 7 思路: 借助数组f[i].表示第i位前面有f[i]个相同的数.对于 8 每个区间(l,r).暴力求前面几个

POJ 3368 Frequent values(RMQ 求区间出现最多次数的数字的次数)

题目链接:http://poj.org/problem?id=3368 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 consisting of indices i and j (1 ≤ i ≤ j ≤ n). For each query, deter

HDU 1806 &amp;&amp; POJ 3368 Frequent values (RMQ)

既然是非降序,那么相等的点一定都聚集在了一块,然后将相等的点分成一段.然后记录每一段的长度,最右端与最左端,然后记录原数列上每个位置上属于哪一段的标号.然后对于每个询问都可以分成3部分,分别计算每一部分,然后对这三部分取最大值. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include

POJ 3368 Frequent values RMQ 训练指南 好题

1 #include<cstdio> 2 #include<cstring> 3 4 const int maxn=1e5+5; 5 const int inf=0x3f3f3f3f; 6 7 inline int max(int x,int y) 8 { 9 return x>y?x:y; 10 } 11 12 int a[maxn]; 13 int left[maxn]; 14 int right[maxn]; 15 int num[maxn]; 16 int dp[ma

poj 3368 Frequent values(线段树解法)

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

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 解题报告

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

[RMQ] [线段树] POJ 3368 Frequent Values

一句话,多次查询区间的众数的次数 注意多组数据!!!! RMQ方法: 预处理 i 及其之前相同的数的个数 再倒着预处理出 i 到不是与 a[i] 相等的位置之前的一个位置, 查询时分成相同的一段和不同的一段 (RMQ) 但是要注意 to[i] 大于查询范围的情况, 以及RMQ时 x < y 的情况!! AC代码: #include<iostream> #include<cstdio> #include<cstring> #include<cstdlib>

POJ 3368 Frequent values (基础RMQ)

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