【BZOJ 4034】【HAOI 2015】树上操作

来源:互联网 发布:python append extend 编辑:程序博客网 时间:2024/06/06 06:38

考虑到在dfs序中,以某个节点为根的子树的编号一定是连续的,所以可以用树剖来做。单点修改和查询都是裸的树剖操作,而区间修改只要找到区间大小就行了,dfs的时候记录一下子树大小即可。
貌似吉老司机给出了树状数组的做法,但我不知道怎么查询QAQ

#include<cmath>#include<cstdio>#include<vector>#include<cstring>#include<iomanip>#include<stdlib.h>#include<iostream>#include<algorithm>#define ll long long#define inf 1000000000#define mod 1000000007#define N 300005using namespace std;struct tree1{    int x,y;     void read(){scanf("%d%d",&x,&y);}} e[N];struct tree2 {int len,siz; ll sum;} tree[N*4];vector<int> v[N];int dep[N],siz[N],fa[N],id[N],son[N],val[N],top[N];int T,num,i,n,x,y,q,opt,delta,st,ed;ll lazy[N*4],h[N];void dfs1(int x,int ftr,int d){    dep[x] = d; siz[x] = 1; son[x] = 0; fa[x] = ftr;    for (int i = 0;i < v[x].size(); i++)        {            int nxt = v[x][i];            if (nxt == ftr) continue;            dfs1(nxt,x,d+1);            siz[x] += siz[nxt];            if (siz[nxt] > siz[son[x]]) son[x] = nxt;        }}void dfs2(int x,int tp){    top[x] = tp; id[x] = ++num;    if (son[x] > 0) dfs2(son[x],tp);    for (int i = 0;i < v[x].size(); i++)        {            int nxt = v[x][i];            if (nxt == fa[x] || nxt == son[x]) continue;            dfs2(nxt,nxt);        }}void build(int l,int r,int rt){    tree[rt].len = r - l + 1;    if (l == r) {tree[rt].sum = val[l]; tree[rt].siz = 1; return;}    int mid = (l + r) >> 1;    build(l,mid,rt << 1);    build(mid+1,r,rt << 1 | 1);    tree[rt].sum = tree[rt<<1].sum + tree[rt<<1|1].sum;    tree[rt].siz = tree[rt<<1].siz + tree[rt<<1|1].siz + 1;}void pushdown(int x){    if (lazy[x] == 0) return;    ll t = lazy[x];    lazy[x<<1] += t; lazy[x<<1|1] += t;    tree[x<<1].sum += tree[x<<1].len * t;    tree[x<<1|1].sum += tree[x<<1|1].len * t;    lazy[x] = 0;}void update(int rt,int l,int r,int L,int R,int s){    if (L <= l && r <= R)         {            lazy[rt] += (ll) s;            tree[rt].sum += (ll) s * tree[rt].len;            return;        }    pushdown(rt);    int mid = (l + r) >> 1;    if (L <= mid) update(rt<<1,l,mid,L,R,s);    if (mid < R) update(rt<<1|1,mid+1,r,L,R,s);    tree[rt].sum = tree[rt<<1].sum + tree[rt<<1|1].sum;}ll query(int rt,int l,int r,int L,int R){    pushdown(rt);    if (L <= l && r <= R) return tree[rt].sum;    int mid = (l + r) >> 1;    ll res = 0;    if (L <= mid) res += query(rt<<1,l,mid,L,R);    if (mid < R) res += query(rt<<1|1,mid+1,r,L,R);    return res;}ll link(int u,int v){    int top1 = top[u]; int top2 = top[v];    ll res = 0;    while (top1 != top2)        {            if (dep[top1] < dep[top2])                {swap(top1,top2); swap(u,v);}            res += query(1,1,n,id[top1],id[u]);            u = fa[top1];            top1 = top[u];        }    if (dep[u] > dep[v]) swap(u,v);    res += query(1,1,n,id[u],id[v]);    return res;}int main(){    scanf("%d%d",&n,&q);    for (i = 1;i <= n; i++) scanf("%d",&h[i]);    for (i = 1;i < n; i++)         {            e[i].read();            v[e[i].x].push_back(e[i].y);            v[e[i].y].push_back(e[i].x);        }               num = 0; dfs1(1,0,1); dfs2(1,1);    for (i = 1;i <= n; i++) val[id[i]] = h[i];      build(1,n,1);     for (i = 1;i <= q; i++)        {            scanf("%d",&opt);            if (opt == 1 || opt == 2)                {                    scanf("%d%d",&x,&delta);                    st = id[x];                    if (opt == 1) ed = st; else ed = st + siz[x] - 1;                    update(1,1,n,st,ed,delta);                }            if (opt == 3)                 {                    scanf("%d",&x);                    ll h = link(x,1);                    printf("%lld\n",h);                }        }    return 0;       }
0 0