树链剖分//模板题
由于存在换根操作
对所有关于节点 u 的修改和查询操作进行分类讨论
若 Root 在 u 的子树中,则不处理 u 所在的 Root 的那颗子树
否则不会有影响
寻找 Root 所在的那颗子树的根可以用倍增求

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string> const int N = 1e5 + ; #define LL long long int topp[N], fa[N], size[N], son[N], deep[N], tree[N], lst[N], rst[N], bef[N], data[N];
int f[N][];
int Tree;
LL W[N << ], F[N << ], S[N << ];
struct Node {
int u, v, nxt;
} G[N << ];
int now, head[N];
int n, m, Root; int opt, T; #define gc getchar() inline int read() {
int x = ; char c = gc;
while(c < '' || c > '') c = gc;
while(c >= '' && c <= '') x = x * + c - '', c = gc;
return x;
} void Add(int u, int v) {G[++ now].v = v; G[now].nxt = head[u]; head[u] = now;} void Dfs_1(int u, int f_, int dep) {
fa[u] = f_, deep[u] = dep, size[u] = ;
for(int i = head[u]; ~ i; i = G[i].nxt) {
int v = G[i].v;
if(v == f_) continue;
f[v][] = u;
Dfs_1(v, u, dep + );
size[u] += size[v];
if(size[son[u]] < size[v]) son[u] = v;
}
} void Dfs_2(int u, int tp) {
topp[u] = tp, tree[u] = ++ Tree, bef[Tree] = u, lst[u] = Tree;
if(!son[u]) {
rst[u] = Tree; return ;
}
Dfs_2(son[u], tp);
for(int i = head[u]; ~ i; i = G[i].nxt) {
int v = G[i].v;
if(v != fa[u] && v != son[u]) Dfs_2(v, v);
}
rst[u] = Tree;
} void Before() {
for(int i = ; ( << i) <= n; i ++)
for(int j = ; j <= n; j ++)
if(f[j][i - ]) f[j][i] = f[f[j][i - ]][i - ];
} #define lson jd << 1
#define rson jd << 1 | 1 void Build_tree(int l, int r, int jd) {
S[jd] = (r - l + );
if(l == r) {
W[jd] = data[bef[l]];
return ;
}
int mid = (l + r) >> ;
Build_tree(l, mid, lson);
Build_tree(mid + , r, rson);
W[jd] = W[lson] + W[rson];
} void Pushdown(int jd) {
if(!F[jd]) return ;
F[lson] += F[jd];
F[rson] += F[jd];
W[lson] += (S[lson] * F[jd]);
W[rson] += (S[rson] * F[jd]);
F[jd] = ;
} void Sec_G(int l, int r, int jd, int x, int y, int num) {
if(x <= l && r <= y) {
F[jd] += num;
W[jd] += (S[jd] * num);
return ;
}
Pushdown(jd);
int mid = (l + r) >> ;
if(x <= mid) Sec_G(l, mid, lson, x, y, num);
if(y > mid) Sec_G(mid + , r, rson, x, y, num);
W[jd] = W[lson] + W[rson];
} void Sec_G_imp(int x, int y, int num) {
int tpx = topp[x], tpy = topp[y];
while(tpx != tpy) {
if(deep[tpx] < deep[tpy]) std:: swap(tpx, tpy), std:: swap(x, y);
Sec_G(, n, , tree[tpx], tree[x], num);
x = fa[tpx];
tpx = topp[x];
}
if(deep[x] < deep[y]) std:: swap(x, y);
Sec_G(, n, , tree[y], tree[x], num);
return ;
} inline int Find(int x, int y) {
int dy = deep[y], dx = deep[x];
int del = deep[y] - deep[x] - ;
for(int i = ; ( << i) <= del; i ++)
if(del & ( << i)) y = f[y][i];
return y;
} LL Answer; void Sec_A(int l, int r, int jd, int x, int y) {
if(x <= l && r <= y) {
Answer += W[jd];
return ;
}
Pushdown(jd);
int mid = (l + r) >> ;
if(x <= mid) Sec_A(l, mid, lson, x, y);
if(y > mid) Sec_A(mid + , r, rson, x, y);
} LL Sec_A_imp(int x, int y) {
int tpx = topp[x], tpy = topp[y];
LL ret = ;
while(tpx != tpy) {
if(deep[tpx] < deep[tpy]) std:: swap(tpx, tpy), std:: swap(x, y);
Answer = ;
Sec_A(, n, , tree[tpx], tree[x]);
ret += Answer;
x = fa[tpx];
tpx = topp[x];
}
if(deep[x] < deep[y]) std:: swap(x, y);
Answer = ;
Sec_A(, n, , tree[y], tree[x]);
ret += Answer;
return ret;
} int main() {
Root = ;
n = read();
for(int i = ; i <= n; i ++) head[i] = -;
for(int i = ; i <= n; i ++) data[i] = read();
for(int i = ; i < n; i ++) {
int u = read();
Add(i + , u), Add(u, i + );
}
Dfs_1(, , );
Dfs_2(, );
Build_tree(, n, );
Before();
int t = read();
for(T = ; T <= t; T ++) {
opt = read();
if(opt == ) Root = read();
else if(opt == ) {
int u = read(), v = read(), x = read();
Sec_G_imp(u, v, x);
} else if(opt == ) {
int u = read(), x = read();
if(Root == u) {
Sec_G(, n, , , n, x);
continue;
}
if(lst[u] <= tree[Root] && tree[Root] <= rst[u]) {
Sec_G(, n, , , n, x);
int Use_son = Find(u, Root);
Sec_G(, n, , lst[Use_son], rst[Use_son], -x);
} else Sec_G(, n, , lst[u], rst[u], x);
} else if(opt == ) {
int x = read(), y = read();
printf("%lld\n", Sec_A_imp(x, y));
} else {
int u = read();
if(Root == u) {
Answer = ;
Sec_A(, n, , , n);
printf("%lld\n", Answer);
continue;
}
LL Now_ans = ;
if(lst[u] <= tree[Root] && tree[Root] <= rst[u]) {
Answer = ;
Sec_A(, n, , , n);
Now_ans += Answer;
int Use_son = Find(u, Root);
Answer = ;
Sec_A(, n, , lst[Use_son], rst[Use_son]);
Now_ans -= Answer;
} else {
Answer = ;
Sec_A(, n, , lst[u], rst[u]);
Now_ans += Answer;
}
printf("%lld\n", Now_ans);
}
}
return ;
}

uoj #139的更多相关文章

  1. uoj #139. 【UER #4】被删除的黑白树 dfs序 贪心

    #139. [UER #4]被删除的黑白树 Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://uoj.ac/problem/139 Descript ...

  2. 【uoj#139】[UER #4]被删除的黑白树 贪心

    题目描述 给出一个 $n$ 个节点的树,$1$ 号点为根.现要将其中一些点染成黑色,使得每个叶子节点(不包括根节点)到根节点路径上的黑点数相同.求最多能够染多少个黑点. 题解 贪心 显然有结论:选择的 ...

  3. ZJOI2019一轮停课刷题记录

    Preface 菜鸡HL终于狗来了他的省选停课,这次的时间很长,暂定停到一试结束,不过有机会二试的话还是可以搞到4月了 这段时间的学习就变得量大而且杂了,一般以刷薄弱的知识点和补一些新的奇怪技巧为主. ...

  4. 虚拟机上装uoj

    前期准备: x64 ubuntu 镜像.vmware.ss账号 注意一定要有64位镜像! ss不是必须的,不过没有的话就等着下载一晚上吧... 首先先装好ubuntu,我装的是ubuntu-16.04 ...

  5. 【UOJ #35】后缀排序 后缀数组模板

    http://uoj.ac/problem/35 以前做后缀数组的题直接粘模板...现在重新写一下模板 注意用来基数排序的数组一定要开到N. #include<cstdio> #inclu ...

  6. 【UOJ #246】【UER #7】套路

    http://uoj.ac/contest/35/problem/246 神奇!我这辈子是想不出这样的算法了. 对区间长度分类讨论:题解很好的~ 我已经弱到爆了,看完题解后还想了一晚上. 题解中&qu ...

  7. 【UOJ #244】【UER #7】短路

    http://uoj.ac/contest/35/problem/244 对其他人来说好简单的一道题,我当时却不会做TWT 注定滚粗啊 题解很好的~ #include<cstdio> #i ...

  8. 【BZOJ 3051】【UOJ #57】【WC 2013】平面图

    http://www.lydsy.com/JudgeOnline/problem.php?id=3051 http://uoj.ac/problem/57 这道题需要平面图转对偶图,点定位,最小生成树 ...

  9. 【UOJ #13】【UER #1】跳蚤OS

    http://uoj.ac/problem/13 建立trie树,然后建立go指针, 和AC自动机里的fail指针差不多, 走到一个快捷方式就从go指针走. 注意在trie树上要保留字符'/',不能用 ...

随机推荐

  1. DotNet 使用阿里云媒体转码服务

    公司项目中一部分文件放到了阿里云 OSS 上,其中有些音频文件是 amr 类型的,在后期使用的时候比较麻烦,所以需要转换成 mp3 的文件,方便以后使用.本来想使用 ffmpeg 处理,但由于文件都存 ...

  2. 【转载】网站配置Https证书系列(一):腾讯云申请免费的SSL证书的流程步骤(即https安全连接使用的证书)

    很多网站为了安全性考虑都会上https安全连接,此时就需要考虑使用SSL证书,其实在腾讯云这边提供有免费的SSL证书申请,登录腾讯云管理控制台后,进入SSL证书管理页面,里面有个申请免费证书.腾讯云申 ...

  3. BeautifulSoup库的安装与使用

    BeautifulSoup库的安装 Win平台:“以管理员身份运行” cmd 执行 pip install beautifulsoup4 演示HTML页面地址:http://python123.io/ ...

  4. web前端如何优化自己的代码

    前端的性能优化主要分为三部分: HTML优化 避免 HTML 中书写 CSS 代码,因为这样难以维护. 使用Viewport加速页面的渲染. 使用语义化标签,减少 CSS 代码,增加可读性和 SEO. ...

  5. Vivado cordic IP求模求角教程

    前言 当需要对复数求模的时候,用FPGA怎么求呢?怎么开根号? 方法1:先求幅值平方和,再使用cordic IP开根号.(蠢办法) 方法2:直接用cordic求取模值. 此处只介绍方法2,资源占用更少 ...

  6. View Controller Programming Guid for iOS 笔记

    1.View Controller 基础 1.1 View Controller 分类 ViewController分为container view controller 和content view ...

  7. 网络基础 InetAddress

    IP地址是IP使用的32位(IPv4)或者128位(IPv6)位无符号数字,它是传输层协议TCP,UDP的基础.InetAddress是Java对IP地址的封装,在java.net中有许多类都使用到了 ...

  8. 网站seo搜索引擎优化

    SEO综合查询方式:http://seo.chinaz.com/网站地址(一般为域名地址),比如:http://seo.chinaz.com/www.test.com 搜索关键字(keywords)优 ...

  9. MVC-Application

    Application简述(不如Cache) 在asp.net环境下,Application对象来自HttpApplictionStat类.它可以在多个请求.连接之间共享公用信息,也可以在各个请求连接 ...

  10. [476] Database Mail is not enabled for agent notifications. Cannot send e-mail to

    配置完DB Mail后JOB的的通知邮件不能发送,日志报错476] Database Mail is not enabled for agent notifications. Cannot send ...