一开始没看懂计算答案的第四部和update2,很迷。然后一直推敲之后才发下我计算的时候漏掉一个关键点。没有把加值的影响放到父节点上。

#include<bits/stdc++.h>
#define M ((l + r) / 2)
#define ls (rt << 1)
#define rs ((rt << 1) | 1)
#define UI unsigned int
using namespace std; const int maxn = 6e5 + ;
vector<int>Gra[maxn];
UI f[maxn], c[maxn], sz[maxn], w[maxn], sum[maxn << ], add[maxn], cntSon[maxn], cntSeson[maxn];
int fa[maxn], N, top[maxn], hSon[maxn];
int edn[maxn], stn[maxn]; /**
stn dfs序的起点, edn dfs序的终点,hSon 重树,add 加重, cntSon 直接子节点数量
sz 树的总大小, cntSeson 2层子节点的总数量, c 子树重复计算个数,
f 未进行操作的子树总值 top 重链的父节点。
**/ ///主要是计算初始值
void dfs1(int u) {
cntSeson[u] = cntSon[u] = hSon[u] = c[u] =;
sz[u] = ;
for(auto v: Gra[u]) {
if(v == fa[u]) continue;
dfs1(v);
sz[u] += sz[v];
cntSon[u] ++;
cntSeson[u] += cntSon[v] + ;
c[u] += sz[v] * cntSon[v];
if(sz[hSon[u]] < sz[v]) hSon[u] = v;
}
f[u] = w[u] * (sz[u] + );
for(auto v: Gra[u]) {
if(v == fa[u]) continue;
f[u] += (sz[u] - sz[v]) * w[v];
w[u] += w[v];
}
} ///dfs序,以及最重要的重树父节点
void dfs2(int u, int t) {
top[u] = t;
stn[u] = ++N;
if(hSon[u]) dfs2(hSon[u], t);
for(auto v: Gra[u]) {
if(v == fa[u] || hSon[u] == v) continue;
dfs2(v, v);
}
edn[u] = N;
} ///查询线段树上的价值
int query(int L, int R, int l, int r, int rt) {
if(L <= l && r <= R) return sum[rt];
int ret = ;
if(M >= L) ret += query(L, R, l, M, ls);
if(M < R) ret += query(L, R, M + , r, rs);
return ret;
} ///作用之后对父节点的影响
void update1(int x, int val) {
while(top[x] != top[]) {
int v = top[x], u = fa[v];
f[u] += (sz[u] - sz[v]) * val;
x = u;
}
} ///存加的价值的影响范围
void update2(int p, UI val, int l, int r, int rt) {
sum[rt] += val;
if(l == r) return ;
if(M >= p) update2(p, val, l, M, ls);
else update2(p, val, M + , r, rs);
} int main() {
freopen("data.txt", "r", stdin);
int n, m, st, ed;
while(~scanf("%d%d", &n, &m)) {
memset(add, , sizeof(add));
memset(sum, , sizeof(sum));
N = ;
for(int i = ; i <= n; i ++)
Gra[i].clear();
for(int i = ; i <= n; i ++) {
scanf("%d", &ed);
fa[i] = ed;
Gra[ed].push_back(i);
Gra[i].push_back(ed);
}
for(int i = ; i <= n; i ++)
scanf("%u", &w[i]);
dfs1();
dfs2(, );
while(m -- ) {
int op, u;
UI x;
scanf("%d", &op);
if(op == ) {
scanf("%d%u", &u, &x);
add[u] += x;
///沿着重树往上预计算重树点价值的作用,之后就不用重复计算这一部分了,这样重树这里就可以成为一个撬棍
update1(u, x * ( + cntSeson[u]));
///将每个点的填加的价值放进去线段树
update2(stn[u], x * (cntSeson[u]+ ), , n, );
} else {
scanf("%d", &u);
UI ans = f[u];
///加值时作用在当前节点上的情况
ans += add[u] * ( + sz[u] * cntSeson[u] - c[u]);
if(fa[u])///加值时作用在子节点上的情况
ans += add[fa[u]] * ( + sz[u] * cntSon[u]);
if(fa[fa[u]])///加值时作用在孙子节点上的情况
ans += add[fa[fa[u]]] * ( + sz[u]);
if(hSon[u])///计算除重树内加值的价值,因为已经在update1计算过了到f中了
ans += (sz[u] - sz[hSon[u]]) * query(stn[hSon[u]], edn[hSon[u]], , n, );
printf("%u\n",ans);
}
}
}
return ;
}

Gardener Bo (树剖 + 问题分解)的更多相关文章

  1. 【61测试】【dp】【二分】【前缀和】【树剖】

    不要问我为什么昨天考的今天才贴解题报告.. 第一题: 给定3个字符串,求它们的最长公共子序列. 解: 考试时知道肯定是LCS的二维再加一维,用三维,可天堂有路你不走,地狱无门你偏来...灵机一动想出来 ...

  2. hdu_5221_Occupation(树剖)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=5221 题意:给你一棵树,每个节点有一定的值,有三种操作: 1 x y 表示占领树上x-y的所有节点,2 ...

  3. 【树链剖分】洛谷P3384树剖模板

    题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节点的值都加上z 操作2: 格式 ...

  4. 【BZOJ 3626】 [LNOI2014]LCA【在线+主席树+树剖】

    题目链接: TP 题解:   可能是我比较纱布,看不懂题解,只好自己想了…… 先附一个离线版本题解[Ivan] 我们考虑对于询问区间是可以差分的,然而这并没有什么卵用,然后考虑怎么统计答案. 首先LC ...

  5. BZOJ_2238_Mst_树剖+线段树

    BZOJ_2238_Mst_树剖+线段树 Description 给出一个N个点M条边的无向带权图,以及Q个询问,每次询问在图中删掉一条边后图的最小生成树.(各询问间独立,每次询问不对之后的询问产生影 ...

  6. BZOJ_3626_[LNOI2014]LCA_离线+树剖

    BZOJ_3626_[LNOI2014]LCA_离线+树剖 题意: 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节点到根的距离+1. 设dep[i]表示点i的深度, ...

  7. BZOJ_2588_Spoj 10628. Count on a tree_树剖+主席树

    BZOJ_2588_Spoj 10628. Count on a tree_树剖+主席树 题意: 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastan ...

  8. BZOJ_4551_[Tjoi2016&Heoi2016]树_树剖+线段树

    BZOJ_4551_[Tjoi2016&Heoi2016]树_树剖+线段树 Description 在2016年,佳媛姐姐刚刚学习了树,非常开心.现在他想解决这样一个问题:给定一颗有根树(根为 ...

  9. BZOJ_2157_旅游_树剖+线段树

    BZOJ_2157_旅游_树剖+线段树 Description Ray 乐忠于旅游,这次他来到了T 城.T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接.为了方便游客到达每个景点但 ...

随机推荐

  1. oracle序列的增、删、改、查及使用

    ----------------------------------------------------------------------创建序列:示例:CREATE SEQUENCE SEQ_SS ...

  2. MyBatis 返回insert操作主键

        应用场景 在向数据库插入数据时,需要保留插入数据的id,以便进行后续的update操作或者将id存入其他表作为外键.但是,在默认情况下,insert操作返回的是一个int值,它并非表示主键id ...

  3. 连连看java版

    主界面 import java.awt.BorderLayout; import java.awt.Color; import java.awt.Container; import java.awt. ...

  4. 批量删除以及将String数组转换成Integer数组的奇淫技巧

    首先在pom.xml文件添加依赖: <!-- bean工具 --> <dependency> <groupId>commons-beanutils</grou ...

  5. Ubuntu上Xilinx ARM交叉编译器安装

    1,Windows中下载交叉编译器 2,在ubuntu中创建zedboard目录,并将交叉编译器复制进来 3,将该交叉编译器设置成可执行程序 chmod  a+x  xilinx-2011.09-50 ...

  6. 20170719 Mysql 配置远端Mysql访问,增加表/存储过程

    -- 1 .在windows 环境中安装Mysql 会按照到默认的C盘当中,如何修改呢--? -- 2. 如何只安装客户端不安装Mysql 数据库服务  --? -- 3. 表的特殊列,默认采用函数值 ...

  7. [py]Python locals() 函数

    Python locals() 函数作用 http://www.runoob.com/python/python-func-locals.html locals() 函数会以字典类型返回当前位置的全部 ...

  8. 【LeetCode每天一题】Next Permutation(下一个排列)

    Implement next permutation, which rearranges numbers into the lexicographically next greater permuta ...

  9. git 冲突解决办法

    1. Pull is not possible because you have unmerged files. 症状:pull的时候 $ git pull Pull is not possible ...

  10. [附POC]Apache Struts2最新(CVE-2017-5638,S02-45)POC

    #! /usr/bin/env python # encoding:utf-8 import urllib2 import sys from poster.encode import multipar ...