zoukankan      html  css  js  c++  java
  • SPOJ 6779 GSS7

    题目描述

    给定一棵树,有N(N100000)个节点,每一个节点都有一个权值xi xi(xi10000)

    你需要执行Q(Q100000)次操作:

    1. 1 a b 查询(a,b)这条链上的最大子段和,可以为空(即输出00)
    2. 2 a b c 将(a,b)这条链上的所有点权变为c (c<=10000)

    输入格式:

    第一行一个整数N

    接下来一行有N个整数表示xi

    接下来N1行,每行两个整数u,v表示uv之间有一条边相连

    接下来一行一个整数QQ

    之后有Q行,每行诸如1 a b或者2 a b c

    输出格式

    对于每一个询问,输出答案

    此题真是数据结构大毒瘤,一开始我认为这不过是在GSS3的基础上套上一个树链剖分而已

    但事实上此题细节极为多,我WA了5遍,这还是在多次在提交前一秒拍出错来的成果

    看到别人说splay比线段树好写,写了LCT等等,可惜我都不会,只能用 树剖+线段树 AC

    现在开始讲细节

    1.线段树的区间推平

    我们除了tag数组以外,还要开一个数组记录是否要推平

    为什么呢,如果要变的val值为0,那么tag[o]=val,就等于0了,那么我们在pushdown的时候就会误认为不需要展开tag

    加入一个数组记录是否要推平就可以避免这样的问题

    void pushdown(int o,int lnum,int rnum)
    {
        if(bian[o])
        {
            sum[o<<1]=tag[o]*lnum;
            lbig[o<<1]=rbig[o<<1]=mbig[o<<1]=max(0,sum[o<<1]);
            tag[o<<1]=tag[o];
            bian[o<<1]=bian[o<<1|1]=1;
            sum[o<<1|1]=tag[o]*rnum;
            lbig[o<<1|1]=rbig[o<<1|1]=mbig[o<<1|1]=max(0,sum[o<<1|1]);
            tag[o<<1|1]=tag[o];
            tag[o]=bian[o]=0;
        }
    }

    2.树剖上区间合并

    因为树剖上较为浅的点,ID值较小,所以在线段树中对应着左边

    所以我们在合并的时候一定要把新query出来的结构体放在左边与ans合并

    ansz=MERGE(query(id[top[u]],id[u],1,n,1),ansz);
    ansy=MERGE(query(id[top[v]],id[v],1,n,1),ansy);

    合并的时候要记得左右分开合并

    到最后将左边翻转,再合并左右

    总体实现如下:

    #include <algorithm>
    #include <iostream>
    #include <cmath>
    #include <cstring>
    #include <map>
    #include <string>
    #include <vector>
    #include <queue>
    #include <stack>
    #include <cstdio>
    #include <cstdlib>
    using namespace std;
    typedef long long ll;
    #define lson l,mid,o<<1
    #define rson mid+1,r,o<<1|1
    inline int read()
    {
        int a=0,q=0;char ch=getchar();
        while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
        if(ch=='-')  q=1,ch=getchar();
        while(ch>='0'&&ch<='9') a=a*10+ch-48,ch=getchar();
        return q?-a:a;
    }
    const int N=100100,INF=0x3f3f3f3f;
    int n,m,u,v,w,op,cnt,tim,temp,top[N],dep[N],head[N],ww[N],wn[N],siz[N],fa[N],son[N],id[N],tag[N<<2],bian[N<<2],lbig[N<<2],rbig[N<<2],mbig[N<<2],sum[N<<2];
    struct EDGE{int nxt,to;}e[N<<1];
    void add(int u,int v){e[++cnt]=(EDGE){head[u],v};head[u]=cnt;}
    struct QAQ
    {
        int lb,rb,mb,s;
        void newone(){lb=0,rb=0,mb=0,s=0;}
    };
    void pushup(int o)
    {
        lbig[o]=max(lbig[o<<1],lbig[o<<1|1]+sum[o<<1]);
        rbig[o]=max(rbig[o<<1|1],rbig[o<<1]+sum[o<<1|1]);
        mbig[o]=max(rbig[o<<1]+lbig[o<<1|1],max(mbig[o<<1],mbig[o<<1|1]));
        sum[o]=sum[o<<1]+sum[o<<1|1];
    }
    void pushdown(int o,int lnum,int rnum)
    {
        if(bian[o])
        {
            sum[o<<1]=tag[o]*lnum;
            lbig[o<<1]=rbig[o<<1]=mbig[o<<1]=max(0,sum[o<<1]);
            tag[o<<1]=tag[o];
            bian[o<<1]=bian[o<<1|1]=1;
            sum[o<<1|1]=tag[o]*rnum;
            lbig[o<<1|1]=rbig[o<<1|1]=mbig[o<<1|1]=max(0,sum[o<<1|1]);
            tag[o<<1|1]=tag[o];
            tag[o]=bian[o]=0;
        }
    }
    QAQ MERGE(QAQ xx,QAQ yy)
    {
        QAQ temp;
        temp.lb=max(xx.lb,yy.lb+xx.s);
        temp.rb=max(yy.rb,xx.rb+yy.s);
        temp.mb=max(xx.rb+yy.lb,max(xx.mb,yy.mb));
        temp.s=xx.s+yy.s;
        return temp;
    }
    void build(int l,int r,int o)
    {
        if(l==r){sum[o]=wn[l];lbig[o]=rbig[o]=mbig[o]=max(sum[o],0);return;}
        int mid=(l+r)>>1;
        build(lson);build(rson);
        pushup(o);
    }
    QAQ query(int L,int R,int l,int r,int o)
    {
        if(L>R) return (QAQ){0,0,0,0}; 
        if(L<=l&&r<=R){return (QAQ){lbig[o],rbig[o],mbig[o],sum[o]};}
        int mid=(l+r)>>1,lb,rb,mb,s=0,e1=0,e2=0;
        pushdown(o,mid-l+1,r-mid);
        QAQ temp1,temp2;
        if(L<=mid) e1=1,temp1=query(L,R,lson);
        if(R> mid) e2=1,temp2=query(L,R,rson);
        if(e1&&e2)
        {
            lb=max(temp1.lb,temp2.lb+temp1.s);
            rb=max(temp2.rb,temp1.rb+temp2.s);
            mb=max(temp1.rb+temp2.lb,max(temp1.mb,temp2.mb));
            s=temp1.s+temp2.s;
        }
        else if(e1)
        {
            lb=temp1.lb;
            rb=temp1.rb;
            mb=temp1.mb;
            s=temp1.s;
        }
        else
        {
            lb=temp2.lb;
            rb=temp2.rb;
            mb=temp2.mb;
            s=temp2.s;
        }
        return (QAQ){lb,rb,mb,s};
    }
    void update(int L,int R,int val,int l,int r,int o)
    {
        if(L<=l&&r<=R)
        {
            sum[o]=(r-l+1)*val;
            lbig[o]=rbig[o]=mbig[o]=max(0,sum[o]);
            tag[o]=val;bian[o]=1;
            return;
        }
        int mid=(l+r)>>1;
        pushdown(o,mid-l+1,r-mid);
        if(L<=mid) update(L,R,val,lson);
        if(R> mid) update(L,R,val,rson);
        pushup(o);
    }
    void dfs1(int u,int ff)
    {
        fa[u]=ff;dep[u]=dep[ff]+1;siz[u]=1;
        int maxson=0;
        for(int i=head[u],v=e[i].to;i;i=e[i].nxt,v=e[i].to) if(v!=ff)
        {
            dfs1(v,u);
            siz[u]+=siz[v];
            if(siz[v]>maxson) maxson=siz[v],son[u]=v;
        }
    }
    void dfs2(int u,int topf)
    {
        id[u]=++tim;top[u]=topf;wn[tim]=ww[u];
        if(!son[u]) return;
        dfs2(son[u],topf);
        for(int i=head[u],v=e[i].to;i;i=e[i].nxt,v=e[i].to) if(v!=fa[u]&&v!=son[u])
            dfs2(v,v);
    }
    void update_tree(int u,int v,int val)
    {
        while(top[u]!=top[v])
        {
            if(dep[top[u]]<dep[top[v]]) swap(u,v);
            update(id[top[u]],id[u],val,1,n,1);
            u=fa[top[u]];
        }
        if(dep[u]>dep[v]) swap(u,v);
        update(id[u],id[v],val,1,n,1);
    }
    QAQ query_tree(int u,int v)
    {
        QAQ ansz,ansy;ansz.newone(),ansy.newone();
        while(top[u]!=top[v])
        {
            if(dep[top[u]]>=dep[top[v]])
            {
                ansz=MERGE(query(id[top[u]],id[u],1,n,1),ansz);
                u=fa[top[u]];
            }
            else
            {
                ansy=MERGE(query(id[top[v]],id[v],1,n,1),ansy);
                v=fa[top[v]];
            }
        }
        if(dep[u]<=dep[v]) ansy=MERGE(query(id[u],id[v],1,n,1),ansy);
        else ansz=MERGE(query(id[v],id[u],1,n,1),ansz);
        swap(ansz.lb,ansz.rb);
        return MERGE(ansz,ansy);
    }
    int main()
    {
    //    freopen("a.in","r",stdin);
    //    freopen("b.out","w",stdout);
        n=read();
        for(int i=1;i<=n;i++) ww[i]=read();
        for(int i=1;i<n;i++)
        {
            u=read(),v=read();
            add(u,v);add(v,u);
        }
        dfs1(1,1);dfs2(1,1);
        build(1,n,1);
    //    for(int i=1;i<=n;i++) printf("%d ",query(i,i,1,n,1).mb);
    //    printf("
    ");
        m=read();
        while(m--)
        {
           op=read();
           if(op==1)
           {
               u=read(),v=read();
               printf("%d
    ",query_tree(u,v).mb);
           }
           else
           {
               u=read(),v=read(),w=read();
               update_tree(u,v,w);
           }
        }
        return 0;
    }
    /*
    
    */
  • 相关阅读:
    微擎二次开发
    linux
    自动自发与强制要求的差别
    金老师的经典著作《一个普通IT人的十年回顾》
    离开了公司,你还有什么
    [转]想靠写程序赚更多钱,写到两眼通红,写得比别人都又快又好好几倍,结果又能如何?
    挨踢人生路--记我的10年18家工作经历 续 .转
    论优越感
    当程序员的那些狗日日子-----转载
    C#语法杂谈
  • 原文地址:https://www.cnblogs.com/cold-cold/p/10056559.html
Copyright © 2011-2022 走看看