[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 ...
随机推荐
- 洛谷——P2149 [SDOI2009]Elaxia的路线
P2149 [SDOI2009]Elaxia的路线 题目描述 最近,Elaxia和w的关系特别好,他们很想整天在一起,但是大学的学习太紧张了,他们 必须合理地安排两个人在一起的时间.Elaxia和w每 ...
- Codeforces Gym 100431D Bubble Sort 水题乱搞
原题链接:http://codeforces.com/gym/100431/attachments/download/2421/20092010-winter-petrozavodsk-camp-an ...
- Codeforces Gym 100431A Achromatic Number 欧拉回路
原题链接:http://codeforces.com/gym/100431/attachments/download/2421/20092010-winter-petrozavodsk-camp-an ...
- luogu P3811 【模板】乘法逆元
题目背景 这是一道模板题 题目描述 给定n,p求1~n中所有整数在模p意义下的乘法逆元. 输入输出格式 输入格式: 一行n,p 输出格式: n行,第i行表示i在模p意义下的逆元. 输入输出样例 输入样 ...
- idea的快捷键和操作
IntelliJ Idea 常用快捷键列表 修改方法如下: 点击 文件菜单(File) –> 点击 设置(Settings… Ctrl+Alt+S), –> 打开设置对话框. 在左侧的 ...
- Ubuntu 16.04下使用Wine安装Windows版的微信(不太完美)
说明: 真的不太完美,别试了:除了需要安装额外的输入法之后,无法上传图片和间接性的BUG出现等等问题. 建议安装网页版的微信:http://www.cnblogs.com/EasonJim/p/711 ...
- BT服务器的搭建(tracker-P2P服务器架设)(转)
文章虽然有点老,但原理差不多. 继上一篇文章(http://www.cnblogs.com/EasonJim/p/6601146.html)介绍了BT的原理,现在来看下BT服务端搭建的原理. 一.BT ...
- SPFA 求带负权的单源最短路
int spfa_bfs(int s) { ///s表示起点. queue <int> q; memset(d,0x3f,sizeof(d)); ///d数组中存下的就是最短路径(存在的话 ...
- php.ini的载入位置
php.ini文件找不到,载入WINDOS下的,但找不到,后来强制-c查找是OK的.思考,为什么载入window下的ini文件.1.可能是有一个默认路径.2.可能没有路径.默认载入. 问题解决:htt ...
- 文本聚类——Kmeans
上两篇文章分别用朴素贝叶斯算法和KNN算法对newgroup文本进行了分类測试.本文使用Kmeans算法对文本进行聚类. 1.文本预处理 文本预处理在前面两本文章中已经介绍,此处(略). 2.文本向量 ...