poj 3368 Frequent values

/*
题意: 有一组不下降的数 a1...an ,查询[s,t]区间内相同元素出现次数的最大值

思路: 首先对给出的原序列 origin 进行统计,将相同的数字放进同一组内:group[i][0],group[i][1],
记录在原序列中该组起点和终点的位置. 再记录原序列每个元素分别属于哪一组
之后就是查询[s,t], 假定元素origin[s],origin[t]分别属于 l_group, r_group组
注意到序列是不下降的,于是有3种可能性:
1.如果元素origin[s],origin[t]属于同一个组,那么该组长度就是我们想要的答 案 t-s+1;
2.如果元素origin[s],origin[t]组号相差1,说明该区间处于两个组,
只要分别研究两侧的分组,取较大值: max(group[l_group][1]-s+1,t-group[r_group][0]+1);
3.如果元素origin[s],origin[t]组号相差大于1,先取出两侧进行研究,取较大值,
然后再用 线段树 ,算出中间的其他分组的最大值,与刚才的的值比较,即得到答案

*/


#include <iostream> // 线段树
using namespace std;

struct segment
{
int l_g,r_g; //记录左右两边分别属于哪个分组
int freq; //freq记录分组[l_g,r_g]的最大值
}tree[500000];

int origin[100005]; //origin记录原始序列
int group[100005][2],belong[100005],tail;

//把相同的元素分到同一组,group[i][0],[1]记录第i组的上下界,而belong[i]是记录origin[i]属于哪一分组的

void init(int n)
{
belong[1]=1;
group[1][0]=group[1][1]=1;
tail=1;
for(int i=2;i<=n;++i)
{
if(origin[i]==origin[i-1])
group[tail][1]++; //下界加1
else

{
++tail; //下一组
group[tail][0]=group[tail][1]=i;

}
belong[i]=tail;
}
}
void built_tree(int n,int l_group,int r_group)
{
tree[n].l_g=l_group;
tree[n].r_g=r_group;
if(l_group==r_group)
{
tree[n].freq=group[l_group][1]-group[l_group][0]+1;
}
else
{
int mid=(l_group+r_group)>>1;
built_tree(2*n,l_group,mid);
built_tree(2*n+1,mid+1,r_group);
tree[n].freq=max(tree[2*n].freq,tree[2*n+1].freq);
}
}
int view_tree(int n,int l_group,int r_group)
{
if (tree[n].l_g==l_group&&tree[n].r_g==r_group) //不用搜索到叶子结点
return tree[n].freq;

else
{
int mid_g=(tree[n].l_g+tree[n].r_g)>>1,a=0,b=0;
if(l_group<=mid_g)
a=view_tree(2*n,l_group,min(r_group,mid_g));
if(r_group>mid_g)
b=view_tree(2*n+1,max(mid_g+1,l_group),r_group);
return max(a,b);
}
}
void query(int s,int t)
{
int res,l_group=belong[s],r_group=belong[t];
if(l_group==r_group)
res=t-s+1;
else
{
res=max(group[l_group][1]-s+1,t-group[r_group][0]+1);
if(l_group+1<r_group)
res=max(res,view_tree(1,l_group+1,r_group-1)); //这里就用到线段树
}

printf("%d\n",res);
}
int main()
{
int n,q,s,t;
while(scanf("%d",&n)&&n)
{
scanf("%d",&q);
for(int i=1;i<=n;++i)
scanf("%d",&origin[i]);
init(n);
built_tree(1,1,tail);
while(q--)
{
scanf("%d%d",&s,&t);
query(s,t);
}
}
return 0;
}

posted on 2011-07-22 16:49  sysu_mjc  阅读(163)  评论(0编辑  收藏  举报

导航