SPOJ 1716 GSS3 zkw线段树

来源:互联网 发布:阿尔法淘宝宝贝下载 编辑:程序博客网 时间:2024/05/18 00:24


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

单点修改也很简单 用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 0
原创粉丝点击