poj3368

来源:互联网 发布:不想找女朋友 知乎 编辑:程序博客网 时间:2024/04/24 18:10

链接:点击打开链接

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

代码:

#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;}


 

0 0
原创粉丝点击