hdu 1806

题目

查询某个区间出现最多的数字.


我都不知道是怎么A的 ==!!


有个重要的特征就是输入的数组中  A[I]<=A[I+1],所以我们可以先离散化,然后记录下每个数字出现的开始位置,和结束位置.

然后就是线段树,每个点除了存左右区间,还要存左边的最多,以及右边的最多,以及最左最右的数字,和这个区间的最多,和最多的这个数字.


然后就是区间的合并了

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
inline int input()
{
    int ret=0;bool IsN=0;char c=getchar();
    while(c<'0'||c>'9') {if(c=='-') IsN=1;c=getchar();}
    while(c>='0'&&c<='9') ret=ret*10+c-'0',c=getchar();
    return IsN?-ret:ret;
}
using namespace std;
map<int,int>m;
map<int,int>::iterator it;
int n,q,k;
int a[100000+10];
int s[100000+10],e[100000+10];

struct node
{
    int l,r;
    int len,ll,lr;
    int lnum,rnum,num;
}root[100010*4];

inline void pushUp(int t)
{
    int l=root[t*2].r-root[t*2].l+1;
    int r=root[t*2+1].r-root[t*2+1].l+1;

    root[t].lnum=root[t*2].lnum;
    root[t].rnum=root[t*2+1].rnum;

    root[t].ll=root[t*2].ll;
    if(root[t*2].ll==l&&root[t*2].rnum==root[t*2+1].lnum) root[t].ll+=root[t*2+1].ll;

    root[t].lr=root[t*2+1].lr;
    if(root[t*2+1].lr==r&&root[t*2].rnum==root[t*2+1].lnum) root[t].lr+=root[t*2].lr;

    int a1=root[t*2].len,a2=root[t*2+1].len;
    int a3=0;
    if(root[t*2].rnum==root[t*2+1].lnum)
    {
        int x=m[root[t*2].rnum];
        int tt=min(e[x],root[t*2+1].r);
        int ss=max(s[x],root[t*2].l);
        a3=tt-ss+1;
    }
    int a=0,id=0;
    if(a1>a) a=a1,id=root[t*2].num;
    if(a2>a) a=a2,id=root[t*2+1].num;
    if(a3>a) a=a3,id=root[t*2].rnum;
    root[t].num=id,root[t].len=a;
}
inline void build(int t,int x,int y)
{
    root[t].l=x,root[t].r=y;
    if(x==y)
    {
        root[t].num=root[t].lnum=root[t].rnum=a[x];
        root[t].len=root[t].ll=root[t].lr=1;
        return;
    }
    int mid=(x+y)>>1;
    build(t*2,x,mid);
    build(t*2+1,mid+1,y);
    pushUp(t);
}
inline int query(int t,int x,int y)
{
    int l=root[t].l,r=root[t].r;
    if(l==x&&r==y)
    {
        return root[t].len;
    }
    int mid=(l+r)>>1;
    if(y<=mid) return query(t*2,x,y);
    else if(x>mid) return query(t*2+1,x,y);
    else
    {
        int a1=query(t*2,x,mid);
        int a2=query(t*2+1,mid+1,y);
        int a3=0;
        if(root[t*2].rnum==root[t*2+1].lnum)
        {
            int xx=m[root[t*2].rnum];
            int tt=min(root[t*2].lr,root[t*2].r-x+1);
            int ss=min(root[t*2+1].ll,y-root[t*2+1].l+1);
            a3=tt+ss;
        }
        return max(a1,max(a2,a3));
    }
}
int main()
{
    while(1)
    {
        n=input();
        if(n==0) break;
        q=input();
        for(int i=1;i<=n;i++) a[i]=input(),m[a[i]]=1;
        k=1;
        for(it=m.begin();it!=m.end();it++) it->second=k++;
        int now=a[1],p=1,i=1;
        for(;i<=n;)
        {
            s[m[now]]=i;
            while(i<=n&&a[i]==now) i++;
            e[m[now]]=i-1;
            if(i<=n) now=a[i];
        }
        build(1,1,n);
        for(int i=0;i<q;i++)
        {
            int x,y;
            x=input(),y=input();
            printf("%d\n",query(1,x,y));
        }
    }
}

再贴个LRJ书上的做法

#define N 100005
int n,q,a[N],val[N],cnt[N],l[N],r[N],id[N];
int x,y,xx,yy,b,num,s,pos;

struct node{
    int l,r,val;
}root[N<<2];
inline void build(int t,int x,int y){
    root[t].l=x,root[t].r=y;
    if(x==y){
        root[t].val=cnt[x];return;
    }
    else{
        int mid=(x+y)>>1;
        build(L,x,mid),build(R,mid+1,y);
        root[t].val=max(root[L].val,root[R].val);
    }
}
inline int query(int t,int x,int y){
    int l=root[t].l,r=root[t].r;
    if(l==x && r==y) return root[t].val;
    int mid=(l+r)>>1;
    if(y<=mid) return query(L,x,y);
    else if(x>mid) return query(R,x,y);
    return max(query(L,x,mid),query(R,mid+1,y));
}

int main(){
    while(1){
        n=input();if(n==0) break;
        q=input();
        clr(val),clr(cnt),clr(l),clr(r),clr(id);
        rep(i,1,n+1) a[i]=input();
        a[n+1]=INF;
        b=a[1],s=1,num=1,pos=0;
        rep(i,2,n+2){
            if(a[i]==b) num++;
            else{
                val[pos]=b,l[pos]=s,r[pos]=i-1,cnt[pos++]=num,s=i,b=a[i],num=1;
            }
        }
        rep(i,0,pos){
            rep(j,l[i],r[i]+1){
                id[j]=i;
            }
        }
/*
        rep(i,0,pos){
            printf("%d %d %d %d \n",val[i],cnt[i],l[i],r[i]);
            }*/
        build(1,0,pos-1);
        rep(ca,1,q+1){
            x=input(),y=input();
            xx=id[x],yy=id[y];
            int Max=max(min(r[xx],y)-x+1,y-max(x,l[yy])+1);
            xx++,yy--;
            if(xx<=yy){
                Max=max(Max,query(1,xx,yy));
            }
            output(Max);
        }
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值