• P3313 [SDOI2014]旅行


    题目

    P3313 [SDOI2014]旅行

    码农题╮(╯▽╰)╭

    为了主席树来的,结果发现是个假标签,又折腾了一个多小时,上一次做树剖题是五个月前了
    果然还是不熟犯了个**错误(分链处理时往上爬是跳到链头的父亲结点)

    想思路(10min)+打代码(20min)+调代码(40min++)

    做法

    树剖+线段树

    对于每种信仰建线段树,然后线段树下标为(dfs)序(标准树剖,不需要再解释了吧)

    然后每次改信仰就从清空原信仰树,添加到新信仰树
    改数值就直接在信仰树上重新复制就好了

    My complete code

    想卡下常还莫名其妙WA了,吸完氧1s左右

    // luogu-judger-enable-o2
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #include<iostream>
    #include<set>
    using namespace std;
    typedef int LL;
    const LL maxn=4000000;
    void Change(LL &now,LL l,LL r,LL c,LL val);
    inline LL Read(){
        LL x(0),f(1);char c=getchar();
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+c-'0',c=getchar();
        return x*f;
    }
    LL n,m,num,tot,nod;
    LL top[maxn],fa[maxn],dep[maxn],bson[maxn],size[maxn],zong[maxn],val[maxn],head[maxn],dfn[maxn],root[maxn];
    struct node{
        LL to,next;
    }dis[maxn];
    inline void Add(LL u,LL v){
        dis[++num]=(node){v,head[u]}; head[u]=num;
    }
    void Dfs1(LL u){
        size[u]=1;
        LL M(0);
        for(LL i=head[u];i;i=dis[i].next){
            LL v(dis[i].to);
            if(v==fa[u])continue;
            fa[v]=u;
            dep[v]=dep[u]+1;
            Dfs1(v);
            size[u]+=size[v];
            if(size[v]>M){
                M=size[v];
                bson[u]=v;
            }
        }
    }//
    void Dfs2(LL u,LL f){
        dfn[u]=++tot; 
        Change(root[zong[u]],1,n,dfn[u],val[u]);
        top[u]=f;
        if(bson[u])
            Dfs2(bson[u],f);//
        for(LL i=head[u];i;i=dis[i].next){
            LL v(dis[i].to);
            if(v==fa[u]||v==bson[u])continue;
            Dfs2(v,v);
        }
    }
    struct Tree{
        LL sum,max,son[2];
    }T[maxn];
    inline void Update(LL now){
        LL son0(T[now].son[0]),son1(T[now].son[1]);
        T[now].max=T[now].sum=0;
        if(son0){
            T[now].sum=T[son0].sum;
            T[now].max=T[son0].max;
        }
        if(son1){
            T[now].sum+=T[son1].sum;
            T[now].max=max(T[now].max,T[son1].max);
        }
    }
    void Change(LL &now,LL l,LL r,LL c,LL zhi){
        if(!now) now=++nod;
        if(l==r){
            T[now].sum=T[now].max=zhi;
            return;
        }
        LL mid(l+r>>1);
        if(c<=mid)
            Change(T[now].son[0],l,mid,c,zhi);
        else
            Change(T[now].son[1],mid+1,r,c,zhi);
        Update(now);
    }
    LL QueryS(LL now,LL l,LL r,LL lt,LL rt){
        if(now==0) return 0;
        if(lt<=l&&rt>=r)
            return T[now].sum;
        LL mid(l+r>>1),ret(0);
        if(lt<=mid)
            ret+=QueryS(T[now].son[0],l,mid,lt,rt);
        if(rt>mid)
            ret+=QueryS(T[now].son[1],mid+1,r,lt,rt);
        return ret;
    }
    inline LL SolveS(LL x,LL y){
        LL fx=top[x],fy=top[y],ans(0),c=zong[x];
        while(fx!=fy){
            if(dep[fx]>=dep[fy]){
                ans+=QueryS(root[c],1,n,dfn[fx],dfn[x]);
                x=fa[fx];
            }else{
                ans+=QueryS(root[c],1,n,dfn[fy],dfn[y]);
                y=fa[fy];
            }
            fx=top[x], fy=top[y];
        }
        if(dfn[x]<=dfn[y])
            ans+=QueryS(root[c],1,n,dfn[x],dfn[y]);
        else
            ans+=QueryS(root[c],1,n,dfn[y],dfn[x]);
        return ans;
    }
    LL QueryM(LL now,LL l,LL r,LL lt,LL rt){
        if(!now) return 0;
        if(lt<=l&&rt>=r)
            return T[now].max;
        LL mid(l+r>>1),ret(0);
        if(lt<=mid)
            ret=max(ret,QueryM(T[now].son[0],l,mid,lt,rt));
        if(rt>mid)
            ret=max(ret,QueryM(T[now].son[1],mid+1,r,lt,rt));
        return ret;
    }
    inline LL SolveM(LL x,LL y){
        LL fx=top[x],fy=top[y],ans(0),c=zong[x];
        while(fx!=fy){
            if(dep[fx]>=dep[fy]){
                ans=max(ans,QueryM(root[c],1,n,dfn[fx],dfn[x]));
                x=fa[fx];
            }else{
                ans=max(ans,QueryM(root[c],1,n,dfn[fy],dfn[y]));
                y=fa[fy];
            }
            fx=top[x], fy=top[y];
        }
        if(dfn[x]<=dfn[y])
            ans=max(ans,QueryM(root[c],1,n,dfn[x],dfn[y]));
        else
            ans=max(ans,QueryM(root[c],1,n,dfn[y],dfn[x]));
        return ans;
    }
    int main(){
        n=Read(),m=Read();
        for(LL i=1;i<=n;++i){
            val[i]=Read(),zong[i]=Read();
        }
        for(LL i=1;i<n;++i){
            LL u(Read()),v(Read());
            Add(u,v),Add(v,u);
        }
        Dfs1(1); Dfs2(1,1);
        while(m--){
            char s[10];
            scanf(" %s",s);
            if(s[0]=='C'){
                if(s[1]=='C'){
                    LL x(Read()),c(Read());
                    Change(root[zong[x]],1,n,dfn[x],0);
                    zong[x]=c;
                    Change(root[zong[x]],1,n,dfn[x],val[x]);
                }else{
                    LL x(Read()),w(Read());
                    val[x]=w;
                    Change(root[zong[x]],1,n,dfn[x],val[x]);
                }
            }else{
                LL x(Read()),y(Read());
                if(s[1]=='S')
                    printf("%d
    ",SolveS(x,y));
                else
                    printf("%d
    ",SolveM(x,y));
            }
        }
    }
    
  • 相关阅读:
    夺命雷公狗---PDO NO:5 使用PDO执行SQL语句之exec
    夺命雷公狗---PDO NO:4 的错误处理模式
    夺命雷公狗---PDO NO:3与连接有关的选项
    夺命雷公狗---PDO NO:02 链接mysql数据库的DSN
    夺命雷公狗---PDO NO:01 PDO介绍和安装
    夺命雷公狗---oop面向对象 NO:5 魔术方法set和get和isset和unset
    夺命雷公狗---oop面向对象 NO:4 封装
    夺命雷公狗---oop面向对象 NO:3 对象中的构造方法和析构方法
    夺命雷公狗---oop面向对象 NO:2 属性的介绍
    夺命雷公狗---oop面向对象 NO:1 面向对象的简介
  • 原文地址:https://www.cnblogs.com/y2823774827y/p/10302822.html
Copyright © 2020-2023  润新知