[bzoj 3720] Gty的妹子树 (树上分块)
树上分块(块状树)
Description
我曾在弦歌之中听过你,
檀板声碎,半出折子戏。
舞榭歌台被风吹去,
岁月深处尚有余音一缕……
Gty神(xian)犇(chong)从来不缺妹子……
他来到了一棵妹子树下,发现每个妹子有一个美丽度……
由于Gty很哲♂学,他只对美丽度大于某个值的妹子感兴趣。
他想知道某个子树中美丽度大于k的妹子个数。
某个妹子的美丽度可能发生变化……
树上可能会出现一只新的妹子……
维护一棵初始有n个节点的有根树(根节点为1),树上节点编号为1-n,每个点有一个权值wi。
支持以下操作:
0 u x 询问以u为根的子树中,严格大于x的值的个数。(u=lastans,x=lastans)
1 u x 把u节点的权值改成x。(u=lastans,x=lastans)
2 u x 添加一个编号为"当前树中节点数+1"的节点,其父节点为u,其权值为x。(u=lastans,x=lastans)
最开始时lastans=0。
Input
输入第一行包括一个正整数n(1<=n<=30000),代表树上的初始节点数。
接下来n-1行,每行2个整数u,v,为树上的一条无向边。
任何时刻,树上的任何权值大于等于0,且两两不同。
接下来1行,包括n个整数wi,表示初始时每个节点的权值。
接下来1行,包括1个整数m(1<=m<=30000),表示操作总数。
接下来m行,每行包括三个整数 op,u,v:
op,u,v的含义见题目描述。
保证题目涉及的所有数在int内。
Output
对每个op=0,输出一行,包括一个整数,意义见题目描述。
Sample Input
2
1 2
10 20
1
0 1 5
Sample Output
2
Solution
这是一道很裸的树上分块题目(又叫块状树)。
我们设一个块的大小为M,对于一个节点,如果它的父亲所属块的大小小于M,则将该点加入其父亲的块,否则将该点加入一个新的块,并建一条从父亲块到新块的边。
在查询u节点为根的子树时,对于和u属于一个块的点暴力枚举,其他点则整块利用二分来计算。对于随机数据,时间复杂度可看做\(O(n * \sqrt{n} * log_n)\) ,可以接受。
Code
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
#define adde(u, v) (e[ecnt] = (edge){v, head[u]}, head[u] = &e[ecnt++])
#define addbe(u, v) (be[blcnt] = (edge){v, bhead[u]}, bhead[u] = &be[blcnt++])
const int maxn = 3e5 + 10, Block = 200;
int ecnt, bcnt, blcnt;
int w[maxn<<1], fa[maxn<<1], bel[maxn];
struct edge {int v; edge *next;} e[maxn<<2], *head[maxn<<1], be[maxn<<1], *bhead[maxn];
struct BLOCK {
int sz, a[Block];
void sort() {std::sort(a, a + sz);}
int find(int k) {return sz - (upper_bound(a, a + sz, k) - a);}
} B[40000];
void build(int u) {
for(edge *k = head[u]; k; k = k->next) if(fa[u] != k->v) {
int tmp;
if(B[bel[u]].sz < Block) {
tmp = bel[k->v] = bel[u];
B[tmp].a[B[tmp].sz++] = w[k->v];
}
else {
tmp = bel[k->v] = ++bcnt;
B[bcnt].a[B[bcnt].sz++] = w[k->v];
addbe(bel[u], tmp);
}
B[tmp].sort();
fa[k->v] = u;
build(k->v);
}
}
void update(int u, int v) {
int tmp = bel[u], k = lower_bound(B[tmp].a, B[tmp].a + B[tmp].sz, w[u]) - B[tmp].a;
B[tmp].a[k] = v; w[u] = v;
B[tmp].sort();
}
int bdfs(int u, int x) {
int res = B[u].find(x);
for(edge *k = bhead[u]; k; k = k->next) {
res += bdfs(k->v, x);
}
return res;
}
int pdfs(int u, int x) {
int res = 0;
if(w[u] > x) res++;
for(edge *k = head[u]; k; k = k->next) if(k->v != fa[u]) {
if(bel[u] == bel[k->v]) res += pdfs(k->v, x);
else res += bdfs(bel[k->v], x);
}
return res;
}
int query(int u, int k) {
int p, res = 0;
res += pdfs(u, k);
return res;
}
int main() {
int n, m, u, v, last = 0, op;
scanf("%d", &n);
for(int i = 1; i < n; i++) scanf("%d%d", &u, &v), adde(u, v), adde(v, u);
for(int i = 1; i <= n; i++) scanf("%d", &w[i]);
fa[1] = -1, B[++bcnt].sz = 1, B[bcnt].a[0] = w[1], bel[1] = bcnt;
build(1);
scanf("%d", &m);
for(int i = 0; i < m; i++) {
scanf("%d%d%d", &op, &u, &v); u ^= last, v ^= last;
if(op == 0) {
printf("%d\n", last = query(u, v));
}
if(op == 1) {
update(u, v);
}
if(op == 2) {
w[++n] = v;
adde(u, n);
fa[n] = u;
int tmp;
if(B[tmp = bel[u]].sz < Block) B[tmp].a[B[tmp].sz++] = v, bel[n] = bel[u];
else B[tmp = ++bcnt].a[B[tmp].sz++] = v, addbe(bel[u], bcnt), bel[n] = bcnt;
B[tmp].sort();
}
}
return 0;
}
[bzoj 3720] Gty的妹子树 (树上分块)的更多相关文章
- BZOJ 3720: Gty的妹子树 [树上size分块]
传送门 题意: 一棵树,询问子树中权值大于$k$的节点个数,修改点权值,插入新点:强制在线 一开始以为询问多少种不同的权值,那道CF的强制在线带修改版,直接吓哭 然后发现看错了这不一道树上分块水题.. ...
- bzoj 3720: Gty的妹子树 块状树
3720: Gty的妹子树 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 412 Solved: 153[Submit][Status] Descr ...
- bzoj 3720 Gty的妹子树 树分块?瞎搞
Gty的妹子树 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2149 Solved: 781[Submit][Status][Discuss] D ...
- BZOJ.3720.Gty的妹子树(树分块)
题目链接 洛谷上惨遭爆零是为什么.. 另外这个树分块算法是假的. /* 插入删除只涉及一个数,故每次可以枚举一遍,而不是重构完后sort */ #include<cmath> #inclu ...
- BZOJ 3744: Gty的妹子序列 【分块 + 树状数组 + 主席树】
任意门:https://www.lydsy.com/JudgeOnline/problem.php?id=3744 3744: Gty的妹子序列 Time Limit: 20 Sec Memory ...
- BZOJ3720 Gty的妹子树 询问分块、主席树
传送门 学到了询问分块的科技-- 对于修改操作,每发生了\(S\)次修改就重构整棵树,小于\(S\)次的修改操作丢到一个队列里面. 对于每一次查询操作,先在主席树上查询当前子树内部大于\(k\)的节点 ...
- luogu P2137 Gty的妹子树(分块,主席树)
询问的化我们可以建主席树.然后修改?,树套树...,最后插入?炸了. 所以我们对操作进行分块. 我们先对整棵树建一个主席树.修改,插入我们先记录下来.然后询问的时候先对主席树查询,然后暴力遍历我们记录 ...
- 【BZOJ3720】Gty的妹子树 块状树
[BZOJ3720]Gty的妹子树 我曾在弦歌之中听过你,檀板声碎,半出折子戏.舞榭歌台被风吹去,岁月深处尚有余音一缕……Gty神(xian)犇(chong)从来不缺妹子……他来到了一棵妹子树下,发现 ...
- bzoj 3744: Gty的妹子序列 主席树+分块
3744: Gty的妹子序列 Time Limit: 15 Sec Memory Limit: 128 MBSubmit: 101 Solved: 34[Submit][Status] Descr ...
随机推荐
- HDU 5790 Prefix(Hash + 主席树)
题目链接 Prefix 题意 给定一个字符串序列,求第$l$个字符串到第$r$个字符串之间有多少个不同的前缀 强制在线 考虑$Hash$ 首先把所有前缀都$hash$出来,按顺序组成一个长度不超过 ...
- k8s之pod控制器
1.生产中,很少会跑一个自主式pod,一般由控制器去创建pod,其配置文件中内嵌了pod的创建方式. pod控制器:ReplicaSet.Deployment.DaemonSet.Job.Cronjo ...
- 好用的Python IDLE Sublime Text 3推荐
Sublime Text 3 下载地址为 LINK, Sublime Text 3 is currently in beta. The latest build is 3114. 参考的激活方式为输入 ...
- assigning to uiimagepickercontrollerdelegate from incompatible type
I have added a UIImagePickerController to a UIViewController. I have assigned the UIImagePickerContr ...
- 邁向IT專家成功之路的三十則鐵律 鐵律二十二:IT人升遷之道-無為
升遷管道是許多人求職時相當重要的考量之一,畢竟人除了很愛錢之外更愛顯赫的頭銜,然而在企業中越顯赫的頭銜,其背後通常有更多的罵名,因為許多人的高官厚爵都是踩著一群人的頭頂爬上去的,隨時哪一天跌了下來,都 ...
- 织梦dede如何去除Power by DedeCms
自从dedecms织梦系统更新到6.7日的版本,底部版权信息调用标签{dede:global.cfg_powerby/}会自动加上织梦官方的链接[Power by DedeCms ],想必很多新用户使 ...
- Android应用开发-小巫CSDN博客客户端开发开篇
2014年9月8日 八月十五 祝各位中秋节快乐 小巫断断续续花了几个星期的时间开发了这么一款应用——小巫CSDN博客,属于私人定制的这样的一款应用,整个客户端的数据全部来自本人博客,是通过爬取本人博客 ...
- treeList获取目录下的所有文件
/// <summary>/// treeList获取目录下的所有文件/// </summary>public static void InitTreeListGetFiles ...
- PS 如何用制作键盘图标
1 键盘可以大致分为笔记本键盘和台式机键盘,颜色一般是黑色或白色.不同的键盘,拍摄角度不同(俯视或者平视)得到的效果也不一样.一般我们根据自己需要得到需要的键盘形式.比如下面别人制作的一套立体键盘,立 ...
- C 标准库 - <stdlib.h>
C 标准库 - <stdlib.h> 简介 stdlib .h 头文件定义了四个变量类型.一些宏和各种通用工具函数. 库变量 下面是头文件 stdlib.h 中定义的变量类型: 序号 变量 ...