SPOJ 1716 GSS3 zkw线段树


这个线段树写起来还算简单 和之前的差不多

单点修改也很简单 用zkw直接改点就行了


#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 5e4 , INF =-0xffffff;
struct stnode
{
    int l,r,m,s;

    void init(int v=INF)
    {
        l=r=m=s=v;
    }
};

inline int max(int a,int b,int c)
{
    return max(a,max(b,c));
}

struct zKWSegmentTree
{
    stnode st[MAXN<<4];
    int sz;

    void init(int n)
    {
        int i,t,end;
        for(sz=1,end=n+2;sz<end;sz<<=1);
        st[sz].init();
        for(i=sz+1,end=sz+n+1;i<end;i++)
        {
            scanf("%d",&t);
            st[i].init(t);
        }
        for(end=sz<<1;i<end;i++)
            st[i].init();

        for(i=sz-1;i>0;i--)
        {
            int l=i<<1,r=l+1;
            st[i].s=st[l].s+st[r].s;
            st[i].l=max(st[l].l,st[l].s+st[r].l);
            st[i].r=max(st[r].r,st[r].s+st[l].r);
            st[i].m=max(st[l].m,st[r].m,st[l].r+st[r].l);
            //printf("[%d]:%d %d %d\n",i,st[i].l,st[i].r,st[i].m);
        }
    }

    void change(int pos,int v)
    {
        pos+=sz;
        st[pos].init(v);
        for(int i=pos>>=1;i>0;i>>=1)
        {
            int l=i<<1,r=l+1;
            st[i].s=st[l].s+st[r].s;
            st[i].l=max(st[l].l,st[l].s+st[r].l);
            st[i].r=max(st[r].r,st[r].s+st[l].r);
            st[i].m=max(st[l].m,st[r].m,st[l].r+st[r].l);
        }
    }

    int quire(int l,int r)
    {
        int lsum,rsum,msum;
        lsum=rsum=msum=INF;
        for(l+=sz-1,r+=sz+1;l^r^1;l>>=1,r>>=1)
        {
            if(~l&1)
            {
                msum=max(st[l^1].m,lsum+st[l^1].l,msum);
                lsum=max(st[l^1].r,lsum+st[l^1].s);
            }
            if(r&1)
            {
                msum=max(st[r^1].m,rsum+st[r^1].r,msum);
                rsum=max(st[r^1].l,rsum+st[r^1].s);
            }
            //printf("%d to %d\t%d %d %d\n",l,r,lsum,rsum,msum);
        }
        return max(max(lsum,rsum,msum),lsum+rsum);
    }
}st;

int main()
{
    int n;
    scanf("%d",&n);
    st.init(n);
    scanf("%d",&n);
    while(n--)
    {
        int op,a,b;
        scanf("%d%d%d",&op,&a,&b);
        if(op)
        {
            printf("%d\n",st.quire(a,b));
        }
        else
            st.change(a,b);
    }
    return 0;
}



/********和题目关联不大分割线

1.GSS2难度有点大  驾驭不来..

2.话说如果建树的时候把用一个数组指针 都指向叶节点的值单点修改也是很快的

想到这里  我又想了想zkw和普通线段树的区别

zkw是完全二叉树  这样left 和 right 找到共同祖先就只要经过相同数量 找爸爸 操作就能找到LCA了

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值