POJ 3368 线段树

来源:互联网 发布:小程序 数据显示 编辑:程序博客网 时间:2024/06/13 22:30

思路:
先统计在第i个位置当前数字已经出现的次数。
维护两个数组,一个是当前位置的数字最后一次出现的位置,另一个是当前位置的数字第一次出现的位置
查找的时候分为两种情况:

  1. 没有和边界相交(意会意会)的数字中的最大值,注意右边界一定要不小于左边边界。
  2. 统计一下和边界相交的数字出现的次数… 如果整个区间是一个数的话要特判。
// by SiriusRen#include <cstdio>#include <algorithm>using namespace std;#define maxn 100005int n,q,a[maxn],b[maxn],tree[maxn*4],f[maxn],xx,yy,jy,ans,jyx,jyy;void build(int l,int r,int pos){    if(l==r){tree[pos]=f[l];return;}    int mid=(l+r)/2;    build(l,mid,pos<<1);build(mid+1,r,pos<<1|1);    tree[pos]=max(tree[pos<<1],tree[pos<<1|1]);}int query(int l,int r,int pos){    if(l>=jyx&&r<=jyy)return tree[pos];    int mid=(l+r)/2;    if(mid>=jyy)return query(l,mid,pos<<1);    else if(mid<jyx)return query(mid+1,r,pos<<1|1);    else return max(query(l,mid,pos<<1),query(mid+1,r,pos<<1|1));}int main(){    while(~scanf("%d",&n)&&n){        scanf("%d",&q);        for(int i=1;i<=n;i++){            scanf("%d",&a[i]);            if(i!=1&&a[i]==a[i-1])f[i]=f[i-1]+1;            else f[i]=1;        }        jy=n;        for(int i=n-1;i>=1;i--)            if(f[i]==f[i+1]-1)a[i]=jy;            else jy=i,a[i]=i;        jy=1;        for(int i=1;i<=n;i++)            if(f[i+1]==f[i]+1)b[i]=jy;            else b[i]=jy,jy=i+1;        build(1,n,1);        for(int i=1;i<=q;i++){            scanf("%d%d",&xx,&yy);            jyx=a[xx]+1,jyy=b[yy]-1;            if(jyx<=jyy)ans=max(query(1,n,1),max(jyx-xx,yy-jyy));            else if(jyx<=yy&&jyy>=xx)ans=max(jyx-xx,yy-jyy);            else ans=yy-xx+1;            printf("%d\n",ans);        }    }}

这里写图片描述

0 0
原创粉丝点击