pku3368 线段树

每个节点额外存5个信息,lx为最左边的端点的序号,lf为跟最左边那个端点序号相等的点的个数,max为这段线段中相等节点个数最大值;rx为最左边的端点的序号,rf为跟最左边那个端点序号相等的点的个数。

 

#include <stdio.h>
#define N 100010
#define MAX(x,y) (x>y?x:y)
int a[N];
struct node
{
    int left,right,mid;
    int lx,rx,max,lf,rf;
}bt[4*N];
 void make(int l,int r,int num)
{
  int temp;
 if (l>r) return ;
    bt[num].left=l;
    bt[num].right=r;
    bt[num].mid=(l+r)/2;
    if(l!=r)
    {
        make(l,bt[num].mid,2*num);
        make(bt[num].mid+1,r,2*num+1);
  bt[num].lx=bt[2*num].lx;bt[num].rx=bt[2*num+1].rx;
  bt[num].lf=bt[2*num].lf;
  bt[num].rf=bt[2*num+1].rf;
  if ((bt[2*num].lx==bt[2*num].rx)&&(bt[2*num].rx==bt[2*num+1].lx)) bt[num].lf=bt[2*num].lf+bt[2*num+1].lf;
  if ((bt[2*num+1].lx==bt[2*num+1].rx)&&(bt[2*num].rx==bt[2*num+1].lx)) bt[num].rf=bt[2*num].rf+bt[2*num+1].rf;
  
  temp=0;
  if (bt[2*num].rx==bt[2*num+1].lx) temp=bt[2*num].rf+bt[2*num+1].lf;
  bt[num].max=MAX(bt[2*num].max,bt[2*num+1].max);
  bt[num].max=MAX(bt[num].max,temp);
    }
    else
    {
  bt[num].lx=bt[num].rx=a[l];
  bt[num].lf=bt[num].rf=1;
  bt[num].max=1;
    }
}
int cal(int l,int r,int num)
{
 int rt, lt;int ll,rr,temp;
    if(bt[num].left==l&&bt[num].right==r)
        return bt[num].max;
    else if(r<=bt[num].mid)
        return cal(l,r,2*num);
    else if(l>bt[num].mid)
        return cal(l,r,2*num+1);
    else
    {
        ll=cal(l,bt[num].mid,2*num);
        rr=cal(bt[num].mid+1,r,2*num+1);
        temp=ll>rr?ll:rr;
        if(bt[2*num].rx==bt[2*num+1].lx)
        {
           
      if(bt[2*num].rf>bt[num].mid-l+1) rt=bt[num].mid-l+1;
            else rt=bt[2*num].rf;
            if(bt[2*num+1].lf>r-bt[num].mid) lt=r-bt[num].mid;
            else lt=bt[2*num+1].lf;
            if(temp<rt+lt) temp=rt+lt;
        }
        return temp;
    }
}
 int main()
{   
    int i,n,m,s,t;
    while(scanf("%d",&n)!=EOF)
    {
  if (n==0) break;
  scanf("%d",&m);
        for(i=1;i<=n;++i) scanf("%d",&a[i]);
        make(1,n,1);
        for(i=1;i<=m;++i)
        {
            scanf("%d%d",&s,&t);
            printf("%d/n",cal(s,t,1));
        }
    }
  return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值