UESTC1425-LCIS 线段树区间合并

做过一个类似的,没注意细节,wrong了一次。。。


ACcode:

#include<stdio.h>
#include<iostream>
using namespace std;

const int size=100000;

struct Node
{
       int li,ri,mi;
       int nl,nr;
       int lazy;
       int sum;
}tre[size<<2];

int Max(int a1,int a2)
{
    return a1>a2?a1:a2;   
}

void pushup(int rt)
{
     int r1=rt<<1,r2=r1+1;
     tre[rt].nl=tre[r1].nl;
     tre[rt].nr=tre[r2].nr;
     tre[rt].mi=Max(tre[r1].mi,tre[r2].mi);
     if (tre[r1].nr<tre[r2].nl) 
        tre[rt].mi=Max(tre[rt].mi,tre[r1].ri+tre[r2].li);
     if (tre[r1].li==tre[r1].sum && tre[r1].nr<tre[r2].nl) tre[rt].li=tre[r1].li+tre[r2].li;
     else tre[rt].li=tre[r1].li;
     if (tre[r2].ri==tre[r2].sum && tre[r1].nr<tre[r2].nl) tre[rt].ri=tre[r1].ri+tre[r2].ri;
     else tre[rt].ri=tre[r2].ri;
}

void build(int rt,int l,int r)
{
     tre[rt].lazy=0;
     tre[rt].sum=r-l+1;
     if (l==r)
     {
        scanf("%d",&tre[rt].nr);
        tre[rt].nl=tre[rt].nr;
        tre[rt].li=tre[rt].ri=tre[rt].mi=1;
        return ;        
     }
     int mid=(l+r)>>1;
     build(rt<<1,l,mid);
     build(rt<<1|1,mid+1,r);
     pushup(rt);
}

void pushdown(int rt)
{
     if (tre[rt].lazy!=0)
     {
        int r1=rt<<1,r2=r1+1;              
        tre[r1].lazy+=tre[rt].lazy;
        tre[r2].lazy+=tre[rt].lazy;    
        tre[r1].nl+=tre[rt].lazy;  
        tre[r1].nr+=tre[rt].lazy;
        tre[r2].nl+=tre[rt].lazy; 
        tre[r2].nr+=tre[rt].lazy; 
        tre[rt].lazy=0;
     }
}

void update(int rt,int l,int r,int L,int R,int v)
{
     if (L<=l&&r<=R)
     {
        tre[rt].lazy+=v;
        tre[rt].nl+=v;
        tre[rt].nr+=v;
        return ;               
     }
     pushdown(rt);
     int mid=(l+r)>>1;
     if (L<=mid) update(rt<<1,l,mid,L,R,v);
     if (R>mid)  update(rt<<1|1,mid+1,r,L,R,v);
     pushup(rt);
}

Node query(int rt,int l,int r,int L,int R)
{
     if (L<=l&&r<=R)
     {
        return tre[rt];
     }
     pushdown(rt);
     int mid=(l+r)>>1;
     int f1=0,f2=0;
     Node r1,r2,tmp;
     if (L<=mid) { r1=query(rt<<1,l,mid,L,R); f1++; }
     if (R>mid)  { r2=query(rt<<1|1,mid+1,r,L,R); f2++; }
     if (f1&&f2)
     {
        tmp.nl=r1.nl;
        tmp.nr=r2.nr;
        tmp.mi=Max(r1.mi,r2.mi);
        if (r1.nr<r2.nl) tmp.mi=Max(tmp.mi,r1.ri+r2.li);
        if (r1.li==r1.sum && r1.nr<r2.nl) tmp.li=r1.li+r2.li;
        else tmp.li=r1.li;
        if (r2.ri==r2.sum && r1.nr<r2.nl) tmp.ri=r1.ri+r2.ri;
        else tmp.ri=r2.ri;
        return tmp;
     }
     else if (f1) return r1;
     else return r2;
}

int main()
{
    int L,R,v;
    int i,n,q,T,cas=0;
    char op[5];
    scanf("%d",&T);
    while (T--)
    {
        scanf("%d %d",&n,&q);
        printf("Case #%d:\n",++cas);
        build(1,1,n);    
        while (q--)
        {
              scanf("%s",op);
              if (op[0]=='q')
              {
                 scanf("%d %d",&L,&R);       
                 Node tmp=query(1,1,n,L,R);
                 printf("%d\n",tmp.mi);        
              }
              else
              {
                  scanf("%d %d %d",&L,&R,&v);   
                  update(1,1,n,L,R,v); 
              }  
        }
    }
    return 0;   
} 
 				    


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值