码迷,mamicode.com
首页 > 其他好文 > 详细

SPOJ 6779 GSS7 - Can you answer these queries VII

时间:2018-12-03 10:26:45      阅读:224      评论:0      收藏:0      [点我收藏+]

标签:type   down   sum   swap   这不   val   turn   splay   upd   

题目描述

给定一棵树,有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("\n");
    m=read();
    while(m--)
    {
       op=read();
       if(op==1)
       {
           u=read(),v=read();
           printf("%d\n",query_tree(u,v).mb);
       }
       else
       {
           u=read(),v=read(),w=read();
           update_tree(u,v,w);
       }
    }
    return 0;
}
/*

*/

 

SPOJ 6779 GSS7 - Can you answer these queries VII

标签:type   down   sum   swap   这不   val   turn   splay   upd   

原文地址:https://www.cnblogs.com/cold-cold/p/10056559.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!