nbut线段树专题W - Frequent values

来源:互联网 发布:完美告白知乎 编辑:程序博客网 时间:2024/05/16 15:42

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 andj (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 nintegers 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.

这题给我的感受很深,题目给的是一些数,但要求的是出现最多的数的个数(一段区间内),所以如果按数值去建立线段树,显然没法得到答案,所以本题我们必须把几个相同的节点当做一个点,然后建立线段树,由于输入数据为不降序,所以很好统计每一个数的个数,以此建立线段树,注意,线段树只能求出完整的一段区间,所以还要配合情况的判断,另外要注意的是,输入的区间和交给线段树的区间不一样,所以要特殊处理(离散化),我们用结构体数组保存一个数集的起点和终点,再用个hash数组保存每个点属于的数集序号,这样,我们通过点,得到其所属数集,再通过判断是不是属于一个数集,2个或者多个来进行求解最大值(只有多个数集的时候才用到线段树)。

#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
#define maxn 100000
int hash[maxn];
int m,n;
struct node2
{
int l,r,c;
}tree[maxn<<2];
struct node
{
int beg,end;
}num[maxn];

void build(int p,int l,int r)
{
tree[p].l=l;
tree[p].r=r;
if(l==r)
{
tree[p].c=num[l].end-num[l].beg+1;
return ;
}
int mid=(l+r)>>1;
build(p<<1,l,mid);
build(p<<1|1,mid+1,r);
tree[p].c=max(tree[p<<1].c,tree[p<<1|1].c);
}

int query(int p,int l,int r)
{
if(l==tree[p].l && r==tree[p].r)
return tree[p].c;
int mid=(tree[p].l+tree[p].r)>>1;
if(r<=mid)
return query(p<<1,l,r);
else if(l>mid)
return query(p<<1|1,l,r);
else
return max(query(p<<1,l,mid),query(p<<1|1,mid+1,r));
}

int main()
{
int n,q,temp;
while(~scanf("%d",&n))
{
if(!n)
break;
scanf("%d",&q);
scanf("%d",&temp);
memset(num,0,sizeof(num));
num[1].beg=1;
num[1].end=1;
hash[1]=1;
int k=1,x,y,last=temp;
for (int i = 2; i <=n; ++i)
{
scanf("%d",&temp);
if(last==temp)
num[k].end=i;
else
{
k++;
last=temp;
num[k].beg=i;
num[k].end=i;
}
hash[i]=k;
}
build(1,1,k);
while(q--)
{
scanf("%d%d",&x,&y);
int s=hash[x],t=hash[y];
if(s==t)
printf("%d\n",y-x+1);
else
{
int n1=num[s].end-x+1;
int n2=0;
int n3=y-num[t].beg+1;
if(t-s>1)
n2=query(1,s+1,t-1);
printf("%d\n",max(max(n1,n3),n2) );
}
}
}
return 0;
}


0 0