您的位置:首页 > 其它

poj3368

2016-01-22 00:29 176 查看
链接:点击打开链接

题意:给出一个不降序列,求出指定区间内出现频率最高的数

代码:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int SIZE=100005;
int a[SIZE<<1],tmp[SIZE<<1];
int maxx[SIZE<<2],sum[SIZE<<1],pos[SIZE<<1];
void build(int l,int r,int rt){
int m;
if(l==r){
maxx[rt]=sum[tmp[l]+100000];
return;
}
m=(l+r)>>1;
build(l,m,rt<<1);
build(m+1,r,rt<<1|1);
maxx[rt]=max(maxx[rt<<1],maxx[rt<<1|1]);
}
int query(int L,int R,int l,int r,int rt){
int m,ans;
ans=0;
if(L<=l&&r<=R)
return maxx[rt];
m=(l+r)>>1;
if(L<=m)
ans=max(ans,query(L,R,l,m,rt<<1));
if(R>m)
ans=max(ans,query(L,R,m+1,r,rt<<1|1));
return ans;
}
int main(){
int n,m,i,j,k,x,y,l,r,ans,cnt;
while(scanf("%d",&n)!=EOF&&n){              //这题关键在于如何处理被区间两端的点
scanf("%d",&m);                         //截断的数出现的频率,剩下的可以用线
memset(pos,0,sizeof(pos));              //段数直接查询,因此预处理每种数最后
memset(sum,0,sizeof(sum));              //出现的位置和出现的次数
for(i=1;i<=n;i++){
scanf("%d",&a[i]);
pos[a[i]+100000]=i;                     //pos记录当前这种数最后一个的位置
sum[a[i]+100000]++;                     //sum记录这种数出现的次数
}                                       //注意有负数,因此变正
memcpy(tmp+1,a+1,sizeof(a));
k=unique(tmp+1,tmp+n+1)-tmp-1;          //k是有多少种数
build(1,k,1);
while(m--){
scanf("%d%d",&x,&y);
l=lower_bound(tmp+1,tmp+k+1,a[x])-tmp;
r=lower_bound(tmp+1,tmp+k+1,a[y])-tmp;
if(r==l){                           //只有一种数时直接输出
printf("%d\n",y-x+1);
continue;
}
ans=0;
if(r-l>1)                           //只有大于两种才需要线段树查询
ans=max(ans,query(l+1,r-1,1,k,1));
ans=max(ans,max(pos[a[x]+100000]-x+1,y-(pos[a[y]+100000]-sum[a[y]+100000])));
printf("%d\n",ans);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: