uoj #139
树链剖分//模板题
由于存在换根操作
对所有关于节点 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的更多相关文章
- uoj #139. 【UER #4】被删除的黑白树 dfs序 贪心
#139. [UER #4]被删除的黑白树 Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://uoj.ac/problem/139 Descript ...
- 【uoj#139】[UER #4]被删除的黑白树 贪心
题目描述 给出一个 $n$ 个节点的树,$1$ 号点为根.现要将其中一些点染成黑色,使得每个叶子节点(不包括根节点)到根节点路径上的黑点数相同.求最多能够染多少个黑点. 题解 贪心 显然有结论:选择的 ...
- ZJOI2019一轮停课刷题记录
Preface 菜鸡HL终于狗来了他的省选停课,这次的时间很长,暂定停到一试结束,不过有机会二试的话还是可以搞到4月了 这段时间的学习就变得量大而且杂了,一般以刷薄弱的知识点和补一些新的奇怪技巧为主. ...
- 虚拟机上装uoj
前期准备: x64 ubuntu 镜像.vmware.ss账号 注意一定要有64位镜像! ss不是必须的,不过没有的话就等着下载一晚上吧... 首先先装好ubuntu,我装的是ubuntu-16.04 ...
- 【UOJ #35】后缀排序 后缀数组模板
http://uoj.ac/problem/35 以前做后缀数组的题直接粘模板...现在重新写一下模板 注意用来基数排序的数组一定要开到N. #include<cstdio> #inclu ...
- 【UOJ #246】【UER #7】套路
http://uoj.ac/contest/35/problem/246 神奇!我这辈子是想不出这样的算法了. 对区间长度分类讨论:题解很好的~ 我已经弱到爆了,看完题解后还想了一晚上. 题解中&qu ...
- 【UOJ #244】【UER #7】短路
http://uoj.ac/contest/35/problem/244 对其他人来说好简单的一道题,我当时却不会做TWT 注定滚粗啊 题解很好的~ #include<cstdio> #i ...
- 【BZOJ 3051】【UOJ #57】【WC 2013】平面图
http://www.lydsy.com/JudgeOnline/problem.php?id=3051 http://uoj.ac/problem/57 这道题需要平面图转对偶图,点定位,最小生成树 ...
- 【UOJ #13】【UER #1】跳蚤OS
http://uoj.ac/problem/13 建立trie树,然后建立go指针, 和AC自动机里的fail指针差不多, 走到一个快捷方式就从go指针走. 注意在trie树上要保留字符'/',不能用 ...
随机推荐
- spring的事务解决方案之@Transactional注解
首先此注解位于 org.springframework.transaction.annotation 这个包路径下面, 事务有两种类别,一种是编程式事务,另一种是声明式事务,显然此注解是声明式事务,这 ...
- 2019杭电多校三 C. Yukikaze and Demons (点分治)
大意: 给定树, 每个点有一个十进制数位, 求有多少条路径组成的十进制数被$k$整除. 点分治, 可以参考CF715C, 转化为求$10^a x+b\equiv 0(mod\space k)$的$x$ ...
- github的pull request是指什么意思?有什么用处(转)
https://www.cnblogs.com/-walker/p/6093277.html
- VS2015按钮方法
protected void btnRoleMemberAdd_Click(object sender ,EventArgs e) { txtEmpID.Text=Coeno.utility.stri ...
- RabbitMQ 应用二
在应用一中,基本的消息队列使用已经完成了,在实际项目中,一定会出现各种各样的需求和问题,RabbitMQ内置的很多强大机制和功能会帮助我们解决很多的问题,下面就一个一个的一起学习一下. 消息响应机制 ...
- 拦截器中获取不到controller注解问题
刚刚在测试接口的时候发现一个奇怪的问题:通过拦截器获取 controller 类注解,有些能获取到,有些又不能获取到,见鬼了. [环境]: 1. springboot :2.2.0.RELEASE [ ...
- sed 删除文本中的内容
删除命令对照表 练习例子 删除/etc/passwd中的第15行 sed -i '1d' passwd 删除/etc/passwd中的8行到14行的所有内容 sed -i '8,14d' passwd ...
- springcloud 之Ribbon客户端负载均衡配置使用
pom.xml添加配置说明:这里服务注册与发现用的是Eureka,所以消费者端需要引入eureka,使用EurekaClient来调用服务 <dependency> <groupId ...
- Linux 命令之 alias
alias 的作用是为命令设置别名,用于提高输入效率 alias 的临时设置 临时设置很简单,直接举例说明 [r@1lin24 ~]$ alias cdlog='cd /var/log' [r@1li ...
- git命令——git status、git diff
前言 当对项目做了更改时,我们通常需要知道具体改了哪些文件,哪些文件更改了没有暂存,哪些文件改了并且已加入到暂存区等待下次commit.上述任务使用git status都可以帮我们解决.但是想要知道文 ...