首页 > 代码库 > poj 3368 Frequent values

poj 3368 Frequent values

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

好复杂的一道线段树+二分的题目,
首先把每一个不同的数看作一个点,建立线段树,然后再加上二分的处理
#include<map>
#include<set>
#include<stack>
#include<queue>
#include<cmath>
#include<vector>
#include<cstdio>
#include<string>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define  inf 0x0f0f0f0f
using namespace std;

const int maxn=100000+10;

struct node
{
    int left,right,mmax;
}tree[maxn*4];
int a[maxn],b[maxn],c[maxn];

void buildtree(int c,int x,int y)
{
    tree[c].left=x;
    tree[c].right=y;
    if (x==y)
    {
        tree[c].mmax=a[x];
        return;
    }
    int mid=x+(y-x)/2;
    buildtree(c*2,x,mid);
    buildtree(c*2+1,mid+1,y);
    tree[c].mmax=max(tree[c*2].mmax,tree[c*2+1].mmax);
}

int get_max(int c,int x,int y)
{
    if (tree[c].left==x && tree[c].right==y) return tree[c].mmax;
    int mid=tree[c].left+(tree[c].right-tree[c].left)/2;
    if (y<=mid) return get_max(c*2,x,y);
    else if (x>mid) return get_max(c*2+1,x,y);
    else return max(get_max(c*2,x,mid),get_max(c*2+1,mid+1,y));
}

int unique(int n)
{
    int cut=1,j=1;
    int ans=1;
    c[1]=b[1];
    for(int i=2;i<=n;i++)
    {
        if (b[i]==c[j]) ans++;
        else
        {
            a[j]=ans;
            ans=1;
            c[++j]=b[i];
        }
    }
    a[j]=ans;
    return j;
}

int find(int x,int y,int v)
{
    while(x<y)
    {
        int m=x+(y-x)/2;
        if (c[m]>=v) y=m;
        else x=m+1;
    }
    return x;
}

int bfind_down(int x,int y,int v)
{
    while(x<y)
    {
        int m=x+(y-x)/2;
        if (b[m]>=v) y=m;
        else x=m+1;
    }
    return x;
}

int bfind_up(int x,int y,int v)
{
    while(x<y)
    {
        int m=x+(y-x)/2;
        if (b[m]<=v) x=m+1;
        else y=m;
    }
    return x;
}

int main()
{
    int n,m,x,y;
    while (scanf("%d",&n)!=EOF && n)
    {
        scanf("%d",&m);
        for (int i=1;i<=n;i++)
        scanf("%d",&b[i]);
        int nown=unique(n);
        buildtree(1,1,nown);
        for (int i=1;i<=m;i++)
        {
            scanf("%d%d",&x,&y);
            if (b[x]==b[y]) {printf("%d\n",y-x+1);continue;}
            int xx=find(1,nown,b[x]);
            int yy=find(1,nown,b[y]);
            if (yy-xx==1){
                int dx=bfind_up(1,n,b[x]); if (b[dx]>b[x]) dx--;
                int dy=bfind_down(1,n,b[y]);
                dx=dx-x+1; dy=y-dy+1;
                printf("%d\n",max(dx,dy));
                continue;
            }
            xx++,yy--;
            int dx=bfind_up(1,n,b[x])-x;
            int dy=y-bfind_down(1,n,b[y])+1;
            printf("%d\n",max(get_max(1,xx,yy),max(dx,dy)));
        }
    }
    return 0;
}

作者 chensunrise