poj 3368 Frequent values(非常变…
2013-05-30 11:05
387 查看
http://poj.org/problem?id=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
Sample Output
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;
}
Frequent values
Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 10191 | Accepted: 3732 |
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;
}
相关文章推荐
- poj&nbsp;3368&nbsp;Frequent&nbsp;values(线段树)
- hdu 1806 Frequent values 线段…
- poj&nbsp;2785&nbsp;4&nbsp;Values…
- 内部赛3 F Frequent values
- poj 1014 _ 多重背包
- ACM: 模拟题 poj 2993
- ACM: 最小费用用最大流 图论题 poj…
- ACM: 动态规划 poj 2192
- ACM: 线段树 poj 2482 煽情的情书!…
- ACM: 动态规划题 poj 2411
- ACM: 图论题 poj 1…
- poj 2942 LA3523 点-双…
- ACM: 暴力题 poj 2741
- poj 3352
- poj 3254Corn Fields
- poj 2449 求第k最短路 A* + SPFA
- poj 3207 简单的2-SAT问题
- A Bug's Life -Poj
- POJ 2236 Wireless Network
- ZZULI_SummerPractice(6) POJ 362…