zoukankan      html  css  js  c++  java
  • BZOJ 4034[HAOI2015]树上操作(树链剖分)

    Description

    有一棵点数为 N 的树,以点 1 为根,且树点有边权。然后有 M 个
    操作,分为三种:
    操作 1 :把某个节点 x 的点权增加 a 。
    操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。
    操作 3 :询问某个节点 x 到根的路径中所有点的点权和。
    Input

    第一行包含两个整数 N, M 。表示点数和操作数。接下来一行 N 个整数,表示树中节点的初始权值。接下来 N-1
    行每行三个正整数 fr, to , 表示该树中存在一条边 (fr, to) 。再接下来 M 行,每行分别表示一次操作。其中
    第一个数表示该操作的种类( 1-3 ) ,之后接这个操作的参数( x 或者 x a ) 。
    Output

    对于每个询问操作,输出该询问的答案。答案之间用换行隔开。

    Sample Input

    5 5

    1 2 3 4 5

    1 2

    1 4

    2 3

    2 5

    3 3

    1 2 1

    3 5

    2 1 2

    3 3
    Sample Output

    6

    9

    13

    HINT

    对于 100% 的数据, N,M<=100000 ,且所有输入数据的绝对值都不会超过 10^6 。

    题解:很裸的树剖题了……然而竟然因为写错了线段树调了一个多小时……emmm,如果分块是O(nlogn)的就好了┑( ̄Д  ̄)┍

    代码如下:

    #include<vector>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define lson root<<1
    #define rson root<<1|1
    #define hi puts("hi");
    using namespace std;
    
    struct node
    {
        long long l,r,lazy,sum;
    } tr[400040];
    long long deep[100010],fa[100010],size[100010],son[100010],id[100010],top[100010],w[100010],c[100010],cnt=0;
    vector<int> g[100010];
    
    void push_up(int root)
    {
        tr[root].sum=tr[lson].sum+tr[rson].sum;
    }
    
    void push_down(int root)
    {
        int mid=(tr[root].l+tr[root].r)>>1;
        tr[lson].sum+=(mid-tr[root].l+1)*tr[root].lazy;
        tr[lson].lazy+=tr[root].lazy;
        tr[rson].sum+=(tr[root].r-mid)*tr[root].lazy;
        tr[rson].lazy+=tr[root].lazy;
        tr[root].lazy=0;
    }
    
    void build(int root,int l,int r)
    {
        if(l==r)
        {
            tr[root].l=l;
            tr[root].r=r;
            tr[root].sum=w[l];
            return ;
        }
        tr[root].l=l;
        tr[root].r=r;
        int mid=(l+r)>>1;
        build(lson,l,mid);
        build(rson,mid+1,r);
        push_up(root);
    }
    
    void add(int root,int l,int r,int x)
    {
        if(l==tr[root].l&&r==tr[root].r)
        {
            tr[root].lazy+=x;
            tr[root].sum+=(tr[root].r-tr[root].l+1)*x;
            return;
        }
        int mid=(tr[root].l+tr[root].r)>>1;
        if(tr[root].lazy)             //
        {
            push_down(root);
        }
        if(l>mid)
        {
            add(rson,l,r,x);            //!!!
        }
        else
        {
            if(r<=mid)
            {
                add(lson,l,r,x);        //!!!
            }
            else
            {
                add(lson,l,mid,x);
                add(rson,mid+1,r,x);
            }
        }
        push_up(root);                //
    }
    
    long long query(int root,int l,int r)
    {
        if(l==tr[root].l&&tr[root].r==r)
        {
            return tr[root].sum;
        }
        int mid=(tr[root].l+tr[root].r)>>1;
        if(tr[root].lazy)
        {
            push_down(root);            //
        }
        if(l>mid)
        {
            return query(rson,l,r);    //!!!
        }
        else
        {
            if(r<=mid)
            {
                return query(lson,l,r);  //!!!
            }
        }
        return query(lson,l,mid)+query(rson,mid+1,r);
    }
    
    void dfs1(int now,int f,int dep)
    {
        deep[now]=dep;
        fa[now]=f;
        size[now]=1;
        int maxson=-1;
        for(int i=0;i<g[now].size();i++)
        {
            if(g[now][i]==f)
            {
                continue;
            }
            dfs1(g[now][i],now,dep+1);
            size[now]+=size[g[now][i]];             //
            if(size[g[now][i]]>maxson)
            {
                son[now]=g[now][i];
                maxson=size[g[now][i]];
            }
        }
    }
    
    void dfs2(int now,int topf)
    {
        id[now]=++cnt;
        w[cnt]=c[now];
        top[now]=topf;
        if(!son[now])
        {
            return ;
        }
        dfs2(son[now],topf);
        for(int i=0;i<g[now].size();i++)
        {
            if(g[now][i]==son[now]||g[now][i]==fa[now])
            {
                continue;
            }
            dfs2(g[now][i],g[now][i]);
        }
    }
    
    void point_add(int x,int val)
    {
        add(1,id[x],id[x],val);
    }
    
    void sub_add(int x,int val)
    {
        add(1,id[x],id[x]+size[x]-1,val);
    }
    
    void path_sum(int x,int y)
    {
        long long ans=0;
        while(top[x]!=top[y])
        {
            if(deep[top[x]]<deep[top[y]])             //
            {
                swap(x,y);
            }
            ans+=query(1,id[top[x]],id[x]);
            x=fa[top[x]];
        }
        if(deep[x]>deep[y])
        {
            swap(x,y);
        }
        ans+=query(1,id[x],id[y]);
        printf("%lld
    ",ans);
    }
    
    int main()
    {
        int n,m,kd,x,a;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            scanf("%lld",&c[i]);
        }
        for(int i=1;i<=n-1;i++)
        {
            int from,to;
            scanf("%d%d",&from,&to);
            g[from].push_back(to);
            g[to].push_back(from);
        }
        dfs1(1,0,1);
        dfs2(1,1);
        build(1,1,n);
        for(int i=1;i<=m;i++)
        {
            scanf("%d",&kd);
            if(kd==1)
            {
                scanf("%d%d",&x,&a);
                point_add(x,a);
            }
            if(kd==2)
            {
                scanf("%d%d",&x,&a);
                sub_add(x,a);
            }
            if(kd==3)
            {
                scanf("%d",&x);
                path_sum(1,x);
            }
        }
    }

    省选一试爆炸了qwq

  • 相关阅读:
    java包和jar包
    java异常总结
    java异常练习2
    java中的异常处理机制_函数覆盖时的异常特点
    React(三)TableBar,ToDoList,Redux案例
    React(二)组件通信
    React(二)组件通信
    React(一)起步
    React(一)起步
    Vue(二)进阶
  • 原文地址:https://www.cnblogs.com/stxy-ferryman/p/8629556.html
Copyright © 2011-2022 走看看