您的位置:首页 > 产品设计 > UI/UE

poj 3368 Frequent values(非常变…

2013-05-30 11:05 387 查看
http://poj.org/problem?id=3368

Frequent values

Time Limit: 2000MSMemory Limit: 65536K
Total Submissions: 10191Accepted: 3732
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

Ulm Local 2007

出处:http://www.cnblogs.com/183zyz/archive/2011/05/11/2043670.html

题意:

给n个数,已经按从大到小顺序排列好,一共有q个询问,每次询问一个区间,问这个区间中出现次数最多的数是什么。
题目数据范围:
数的个数,1 <= n <= 100000
询问次数,1 <= q <= 100000
每个数的大小,-100000 <= ai <=
100000

很容易想到建立线段树,并在线段树的每个节点中保存区间中出现次数最多的数
需要解决的问题,两个子结点的信息如何合并到父节点。
很显然,子结点中出现次数最多的数不一定就是父节点中出现次数最多的数,
有可能一个数在两个子结点中的出现次数都不是最多,但是子结点合并成父节点后,这个数的出现次数就最多了
考虑到题目中的重要条件,数组中的数是有序的!

当左子节点区间最右的数与右子区间最左的数相等时,这个相等的数的出现次数可能最多
需要记录节点区间最左和最右的数的信息


3368 Frequent values(非常变形)" TITLE="poj 3368 Frequent values(非常变形)" />
我的想法就是定义一个结构体:
struct node{
int l,r;
int count,num;
int lcount,lnum;
int rcount,rnum;
};
l,r存该节点的边界。 count存该节点中出现最多的数字的个数,num存该节点中出现最多的数字。
lcount 存该节点左端连续出现的数字的个数, lnum存该节点左端连续出现的数字。
rcount 存该节点右端连续出现的数字的个数, rnum存该节点右端连续出现的数字。
建树的时候初始化的时候比较麻烦一点, 每次询问的时候不是很麻烦。。
# include

# include

# define N 100005

struct node

{

int r,l;//l,r存该节点的边界

int
num,count;//count存该节点中出现最多的数字的个数,num存该节点中出现最多的数字。

int rnum,rcount;//rcount 存该节点右端连续出现的数字的个数,
rnum存该节点右端连续出现的数字。

int lnum,lcount;//lcount 存该节点左端连续出现的数字的个数,
lnum存该节点左端连续出现的数字。

}tree[4*N];

int a
,MAX;

void bulid(int l,int r,int t)//建树

{

int mid,ans;

tree[t].l=l;

tree[t].r=r;

if(l==r)

{

tree[t].count=tree[t].lcount=tree[t].rcount=1;

tree[t].num=tree[t].lnum=tree[t].rnum=a[l];

return;

}

mid=(l+r)/2;

bulid(l,mid,2*t);

bulid(mid+1,r,2*t+1);

if(tree[2*t].count>=tree[2*t+1].count)
//左边结点出现最多的数字的个数大于右边,更新父亲结点

{

tree[t].num=tree[2*t].num;

tree[t].count=tree[2*t].count;

}

else

{

tree[t].num=tree[2*t+1].num;

tree[t].count=tree[2*t+1].count;

}

tree[t].lnum=tree[2*t].lnum;

tree[t].lcount=tree[2*t].lcount;

tree[t].rnum=tree[2*t+1].rnum;

tree[t].rcount=tree[2*t+1].rcount;

if(tree[2*t].rnum==tree[2*t+1].lnum)//节点右端连续出现的数字与左端的数字相同

{

ans=tree[2*t].rcount+tree[2*t+1].lcount;//用ans保存最大数字的个数

if(ans>tree[t].count)

{

tree[t].count=ans;

tree[t].num=tree[2*t].rnum;

}

if(tree[2*t+1].lnum==tree[2*t].lnum)
tree[t].lcount+=tree[2*t+1].lcount;

if(tree[2*t].rnum==tree[2*t+1].rnum)
tree[t].rcount+=tree[2*t].rcount;

}

}

void updata(int l,int r,int t)

{

int mid,ans1,ans2;

if(tree[t].l==l
&& tree[t].r==r)

{

if(tree[t].count>MAX)
MAX=tree[t].count;

return;

}

if(r<=tree[2*t].r)
updata(l,r,2*t);

else if(l>=tree[2*t+1].l)
updata(l,r,2*t+1);

else

{

mid=tree[2*t].r;

updata(l,mid,2*t);

updata(mid+1,r,2*t+1);

if(tree[2*t].rnum ==
tree[2*t+1].lnum)

{

if(a[l]!=tree[2*t].rnum)
ans1=tree[2*t].rcount;

else
ans1=mid-l+1;

if(a[r]!=tree[2*t+1].lnum)
ans2=tree[2*t+1].lcount;

else
ans2=r-mid;

if(ans1+ans2
> MAX) MAX=ans1+ans2;

}

}

}

int main()

{

int i,Q,start,end,n;

while(scanf("%d",&n)!=EOF
&& n)

{

scanf("%d",&Q);

for(i=1;i<=n;i++)

scanf("%d",&a[i]);

bulid(1,n,1);

while(Q--)

{

scanf("%d%d",&start,&end);

if(start==end)

{

printf("1\n");

continue;

}

MAX=0;

updata(start,end,1);

printf("%d\n",MAX);

}

}

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: