• P3178 [HAOI2015]树上操作 树链剖分


    这个题就是一道树链剖分的裸题,但是需要有一个魔性操作___编号数组需要开longlong!!!震惊!真的神奇.

    题干:

    题目描述
    
    有一棵点数为 N 的树,以点 1 为根,且树点有边权。然后有 M 个操作,分为三种:操作 1 :把某个节点 x 的点权增加 a 。操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。操作 3 :询问某个节点 x 到根的路径中所有点的点权和。
    输入输出格式
    输入格式:
    
    第一行包含两个整数 N, M 。表示点数和操作数。接下来一行 N 个整数,表示树中节点的初始权值。接下来 N-1 行每行两个正整数 from, to , 表示该树中存在一条边 (from, to) 。再接下来 M 行,每行分别表示一次操作。其中第一个数表示该操作的种类( 1-3 ) ,之后接这个操作的参数( x 或者 x a ) 。
    输出格式:
    对于每个询问操作,输出该询问的答案。答案之间用换行隔开。
    输入输出样例
    输入样例#1: 复制
    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
    输出样例#1: 复制
    6
    9
    13
    说明
    对于 100% 的数据, N,M<=100000 ,且所有输入数据的绝对值都不
    会超过 10^6

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<ctime>
    #include<queue>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    #define duke(i,a,n) for(int i = a;i <= n;i++)
    #define lv(i,a,n) for(int i = a;i >= n;i--)
    #define clean(a) memset(a,0,sizeof(a))
    const int INF = 1 << 30;
    typedef long long ll;
    typedef double db;
    template <class T>
    void read(T &x)
    {
        char c;
        bool op = 0;
        while(c = getchar(), c < '0' || c > '9')
            if(c == '-') op = 1;
        x = c - '0';
        while(c = getchar(), c >= '0' && c <= '9')
            x = x * 10 + c - '0';
        if(op) x = -x;
    }
    template <class T>
    void write(T x)
    {
        if(x < 0) putchar('-'), x = -x;
        if(x >= 10) write(x / 10);
        putchar('0' + x % 10);
    }
    const int N = 200010;
    struct node
    {
        ll l,r;
        int nxt;
    }a[N];
    int len = 0,lst[N];
    void add(ll x,ll y)
    {
        a[++len].l = x;
        a[len].r = y;
        a[len].nxt = lst[x];
        lst[x] = len;
    }
    ll n,m;
    ll tree[N << 2],lazy[N << 2];
    ll siz[N],son[N],cnt = 0,id[N];
    ll A[N];
    ll top[N],f[N],rk[N],dep[N];
    int vis[N];
    void dfs1(ll u,ll fa,ll depth)
    {
        f[u] = fa;
        siz[u] = 1;
        dep[u] = depth;
        for(int k = lst[u];k;k = a[k].nxt)
        {
            ll y = a[k].r;
            if(y == fa) continue;
            dfs1(y,u,depth + 1);
            siz[u] += siz[y];
            if(!son[u] || siz[son[u]] < siz[y])
            son[u] = y;
        }
    }
    void dfs2(ll u,ll t)
    {
        vis[u] = 1;
        top[u] = t;
        id[u] = ++cnt;
        rk[cnt] = u;
        if(!son[u]) return;
        dfs2(son[u],t);
        for(int k = lst[u];k;k = a[k].nxt)
        {
            ll y = a[k].r;
            if(y == son[u] || y == f[u] || vis[y] == 1)
            continue;
            dfs2(y,y);
        }
    }
    void build(ll o,ll l,ll r)
    {
        if(l == r)
        {
            tree[o] = A[rk[l]];
            return;
        }
        ll mid = (l + r) >> 1;
        build(o << 1,l,mid);
        build(o << 1 | 1,mid + 1,r);
        tree[o] = tree[o << 1] + tree[o << 1 | 1];
    }
    void push_down(ll o,ll l,ll r)
    {
        if(lazy[o] != 0)
        {
            ll mid = (l + r) >> 1;
            tree[o << 1] += (ll)(mid - l + 1) * lazy[o];
            tree[o << 1 | 1] += (ll)(r - mid) * lazy[o];
            lazy[o << 1] += lazy[o];
            lazy[o << 1 | 1] += lazy[o];
            lazy[o] = 0;
        }
    }
    void sin_change(ll o,ll l,ll r,ll k,ll w)
    {
        if(l == r)
        {
            tree[o] += w;
            lazy[o] += w;
            return;
        }
        ll mid = (l + r) >> 1;
        push_down(o,l,r);
        if(mid >= k)
        sin_change(o << 1,l,mid,k,w);
        else
        sin_change(o << 1 | 1,mid + 1,r,k,w);
    }
    void all_change(ll o,ll l,ll r,ll x,ll y,ll w)
    {
        if(l == x && r == y)
        {
            tree[o] += (r - l + 1) * w;
            lazy[o] += w;
            return;
        }
        push_down(o,l,r);
        ll mid = (l + r) >> 1;
        if(mid >= y)
        all_change(o << 1,l,mid,x,y,w);
        else if(mid < x)
        all_change(o << 1 | 1,mid + 1,r,x,y,w);
        else
        {
            all_change(o << 1,l,mid,x,mid,w);
            all_change(o << 1 | 1,mid + 1,r,mid + 1,y,w);
        }
        tree[o] = tree[o << 1] + tree[o << 1 | 1];
    }
    ll query(ll o,ll l,ll r,ll x,ll y)
    {
        if(l == x && r == y)
            return tree[o];
        push_down(o,l,r);
        ll mid = (l + r) >> 1;
        if(mid >= y)
        return query(o << 1,l,mid,x,y);
        else if(mid < x)
        return query(o << 1 | 1,mid + 1,r,x,y);
        else
        {
            ll ans = 0;
            ans += query(o << 1,l,mid,x,mid);
            ans += query(o << 1 | 1,mid + 1,r,mid + 1,y);
            return ans;
        }
    }
    ll work(int x,int y)
    {
        ll ans = 0;
        while(top[x] != top[y])
        {
            if(dep[top[x]] < dep[top[y]])
            swap(x,y);
            ll res = query(1,1,n,id[top[x]],id[x]);
            ans += res;
            x = f[top[x]];
        }
        if(dep[x] > dep[y])
        swap(x,y);
        ans += query(1,1,n,id[x],id[y]);
        return ans;
    }
    int main()
    {
        read(n);read(m);
        duke(i,1,n)
        read(A[i]);
        duke(i,1,n - 1)
        {
            ll x,y;
            read(x);read(y);
            add(x,y);
            add(y,x);
        }
        dfs1(1,0,1);
        dfs2(1,1);
        int ok;
        build(1,1,n);
        /*duke(i,1,n)
        printf("%d ",top[i]);
        cout<<endl;*/
        /*duke(i,1,n)
        printf("%d ",tree[i]);
        cout<<endl;*/
        duke(i,1,m)
        {
            read(ok);
            if(ok == 1)
            {
                ll x;ll y;
                read(x);read(y);
                all_change(1,1,n,id[x],id[x],y);
            }
            else if(ok == 2)
            {
                ll x;ll y;
                read(x);read(y);
                all_change(1,1,n,id[x],id[x] + siz[x] - 1,y);
            }
            else
            {
                ll x;
                read(x);//printf("!!!%d %d
    ",id[1],id[x]);
                printf("%lld
    ",work(1,x));
            }
            /*duke(i,1,n)
            printf("%d ",lazy[i]);
            cout<<endl;*/
        }
        return 0;
    }
    /*
    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
    */
  • 相关阅读:
    local 不能解析为127.0.0.1
    完全使用接口方式调用WCF 服务
    【人生】自己对于求职应聘的一些感受
    OO的经典例子
    剪刀、石头、布机器人比赛
    TextTree 文本资料收集轻量级工具
    两个代替重复输入的小工具
    桌面助手 Desktop Helper 自动帮你关闭指定的窗口
    磁盘可用空间平衡
    用C#制造可以继承的“枚举”
  • 原文地址:https://www.cnblogs.com/DukeLv/p/9717720.html
Copyright © 2020-2023  润新知