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\n",id[1],id[x]);
            printf("%lld\n",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
*/

 

posted @ 2018-09-28 11:37  DukeLv  阅读(147)  评论(0编辑  收藏  举报