zoukankan      html  css  js  c++  java
  • 题解 [CF916E] Jamie and Tree

    题面

    解析

    这题考试时刚了四个小时.

    结果还是爆零了

    主要就是因为(lca)找伪了.

    我们先考虑没有操作1,那就是裸的线段树.

    在换了根以后,主要就是(lca)不好找(分类讨论伪了).

    我们将一开始以(1)为根的图作为原图.

    仔细思考一下,

    我们会发现只有当原图上的(lca)(1)和当前的根的路径上时,(lca)才会发生变化.

    考试时怎么没发现

    而当(lca)变化后,我们画一下图,

    就会发现,

    现在的(lca)就是两个点与根的(lca)中深度较大的一个.

    (这个(yy)一下就能明白了)

    然后,我们再考虑修改查询.(实际上它们的道理是一样的)

    假设我们要修改查询的是(p)的子树,

    如果根不在(p)的子树里,就直接来就行了,

    否则,从根到(p)的路径上的所有分出去的点就不会被修改(画下图就能明白),

    所以我们直接全图加一下,

    设根在(p)的儿子(k)的子树里,

    那么将(k)的子树全部减一下就行了.

    至于找(k),可以用倍增,

    修改查询可以用线段树&树链剖分.

    code:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #define int long long
    #define ls(a) a<<1
    #define rs(a) a<<1|1
    #define fre(x) freopen(x".in","r",stdin),freopen(x".out","w",stdout)
    using namespace std;
    
    inline int read(){
        int sum=0,f=1;char ch=getchar();
        while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0' && ch<='9'){sum=sum*10+ch-'0';ch=getchar();}
        return f*sum;
    }
    
    const int N=600001;
    struct tree{int l,r,sum,tag;}t[N<<1];
    struct node{int val,fa,size,son,dep,id,top;}a[N];
    struct edge{int to,next;}e[N<<1];
    int n,m,rt=1;
    int head[N],cnt=0;
    int tot,pla[N],f[N][21];
    
    inline void add(int x,int y){
        e[++cnt]=(edge){head[x],y};head[x]=cnt;
    }
    
    void dfs1(int x,int fa){
        a[x].size=1;a[x].fa=fa;a[x].dep=a[fa].dep+1;
        f[x][0]=fa;
        for(int i=1;i<=20;i++) f[x][i]=f[f[x][i-1]][i-1];
        for(int i=head[x];i;i=e[i].to){
            int k=e[i].next;if(k==fa) continue;
            dfs1(k,x);a[x].size+=a[k].size;
            if(!a[x].son||a[k].size>a[a[x].son].size) a[x].son=k;
        }
    }
    
    void dfs2(int x,int top){
        a[x].top=top;a[x].id=++tot;pla[tot]=x;
        if(a[x].son) dfs2(a[x].son,top);
        for(int i=head[x];i;i=e[i].to){
            int k=e[i].next;if(k==a[x].fa||k==a[x].son) continue;
            dfs2(k,k);
        }
    }
    
    inline int lca(int x,int y){
        while(a[x].top!=a[y].top){
            if(a[a[x].top].dep<a[a[y].top].dep) swap(x,y);
            x=a[a[x].top].fa;
        }
        if(a[x].dep>a[y].dep) swap(x,y);
        return x;
    }
    
    inline void pushup(int p){
        t[p].sum=t[ls(p)].sum+t[rs(p)].sum;
    }
    
    inline void pushdown(int p){
        if(!t[p].tag) return ;
        int l=ls(p),r=rs(p);
        t[l].tag+=t[p].tag;t[r].tag+=t[p].tag;
        t[l].sum+=(t[l].r-t[l].l+1)*t[p].tag;
        t[r].sum+=(t[r].r-t[r].l+1)*t[p].tag;
        t[p].tag=0;
    }
    
    inline void sg_build(int p,int l,int r){
        t[p].l=l;t[p].r=r;
        if(l==r){t[p].sum=a[pla[l]].val;return ;}
        int mid=(l+r)>>1;
        sg_build(ls(p),l,mid);sg_build(rs(p),mid+1,r);
        pushup(p);
    }
    
    inline void sg_change(int p,int l,int r,int w){
        if(t[p].l>=l&&t[p].r<=r){
            t[p].sum+=(t[p].r-t[p].l+1)*w;t[p].tag+=w;
            return ;
        }
        pushdown(p);
        int mid=(t[p].l+t[p].r)>>1;
        if(l<=mid) sg_change(ls(p),l,r,w);
        if(r>mid) sg_change(rs(p),l,r,w);
        pushup(p);
    }
    
    inline int sg_query(int p,int l,int r){
        if(t[p].l>=l&&t[p].r<=r) return t[p].sum;
        pushdown(p);
        int mid=(t[p].l+t[p].r)>>1,ret=0;
        if(l<=mid) ret+=sg_query(ls(p),l,r);
        if(r>mid) ret+=sg_query(rs(p),l,r);
        pushup(p);
        return ret;
    }
    
    inline int isson(int x,int fa){return a[x].id>=a[fa].id&&a[x].id<=a[fa].id+a[fa].size-1;}
    
    inline void change(int x,int y,int w){
        int p=lca(x,y);
        int f1=lca(p,rt);
        if(f1==p){
            f1=lca(x,rt);int f2=lca(y,rt);
            if(a[f1].dep>a[f2].dep) p=f1;
            else p=f2;
        }
        if(!isson(rt,p)) sg_change(1,a[p].id,a[p].id+a[p].size-1,w);
        else{
            sg_change(1,1,n,w);int k=rt;
            if(isson(k,p)&&rt!=p){
                for(int i=20;i>=0;i--)
                    if(a[f[k][i]].dep>a[p].dep) k=f[k][i];
                sg_change(1,a[k].id,a[k].id+a[k].size-1,-w);
            }
        }
    }
    
    inline void ask(int p){
        int ret=0;
        if(a[rt].id>a[p].id+a[p].size-1||a[rt].id<a[p].id) ret=sg_query(1,a[p].id,a[p].id+a[p].size-1);
        else{
            ret+=sg_query(1,1,n);int k=rt;
            if(isson(k,p)&&rt!=p){
                for(int i=20;i>=0;i--)
                    if(a[f[k][i]].dep>a[p].dep) k=f[k][i];
                ret-=sg_query(1,a[k].id,a[k].id+a[k].size-1);
            }
        }
        printf("%lld
    ",ret);
    }
    
    signed main(){
        n=read();m=read();
        for(int i=1;i<=n;i++) a[i].val=read();
        for(int i=1;i<n;i++){int x=read(),y=read();add(x,y);add(y,x);}
        dfs1(1,0);dfs2(1,1);sg_build(1,1,n);
        for(int i=1;i<=m;i++){
            int opt=read(),x=read();
            if(opt==1) rt=x;
            else if(opt==2) {int y=read(),w=read();change(x,y,w);}
            else if(opt==3) ask(x);
        }
        return 0;
    }
    /*
    6 7
    1 4 2 8 5 7
    1 2
    3 1
    4 3
    4 5
    3 6
    3 1
    2 4 6 3
    3 4
    1 6
    2 2 4 -5
    1 4
    3 3
     */
    
    
  • 相关阅读:
    leetcode 131. Palindrome Partitioning
    leetcode 526. Beautiful Arrangement
    poj 1852 Ants
    leetcode 1219. Path with Maximum Gold
    leetcode 66. Plus One
    leetcode 43. Multiply Strings
    pytorch中torch.narrow()函数
    pytorch中的torch.repeat()函数与numpy.tile()
    leetcode 1051. Height Checker
    leetcode 561. Array Partition I
  • 原文地址:https://www.cnblogs.com/zsq259/p/11186202.html
Copyright © 2011-2022 走看看