树上分块(块状树)


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的妹子树 (树上分块)的更多相关文章

  1. BZOJ 3720: Gty的妹子树 [树上size分块]

    传送门 题意: 一棵树,询问子树中权值大于$k$的节点个数,修改点权值,插入新点:强制在线 一开始以为询问多少种不同的权值,那道CF的强制在线带修改版,直接吓哭 然后发现看错了这不一道树上分块水题.. ...

  2. bzoj 3720: Gty的妹子树 块状树

    3720: Gty的妹子树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 412  Solved: 153[Submit][Status] Descr ...

  3. bzoj 3720 Gty的妹子树 树分块?瞎搞

    Gty的妹子树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2149  Solved: 781[Submit][Status][Discuss] D ...

  4. BZOJ.3720.Gty的妹子树(树分块)

    题目链接 洛谷上惨遭爆零是为什么.. 另外这个树分块算法是假的. /* 插入删除只涉及一个数,故每次可以枚举一遍,而不是重构完后sort */ #include<cmath> #inclu ...

  5. BZOJ 3744: Gty的妹子序列 【分块 + 树状数组 + 主席树】

    任意门:https://www.lydsy.com/JudgeOnline/problem.php?id=3744 3744: Gty的妹子序列 Time Limit: 20 Sec  Memory ...

  6. BZOJ3720 Gty的妹子树 询问分块、主席树

    传送门 学到了询问分块的科技-- 对于修改操作,每发生了\(S\)次修改就重构整棵树,小于\(S\)次的修改操作丢到一个队列里面. 对于每一次查询操作,先在主席树上查询当前子树内部大于\(k\)的节点 ...

  7. luogu P2137 Gty的妹子树(分块,主席树)

    询问的化我们可以建主席树.然后修改?,树套树...,最后插入?炸了. 所以我们对操作进行分块. 我们先对整棵树建一个主席树.修改,插入我们先记录下来.然后询问的时候先对主席树查询,然后暴力遍历我们记录 ...

  8. 【BZOJ3720】Gty的妹子树 块状树

    [BZOJ3720]Gty的妹子树 我曾在弦歌之中听过你,檀板声碎,半出折子戏.舞榭歌台被风吹去,岁月深处尚有余音一缕……Gty神(xian)犇(chong)从来不缺妹子……他来到了一棵妹子树下,发现 ...

  9. bzoj 3744: Gty的妹子序列 主席树+分块

    3744: Gty的妹子序列 Time Limit: 15 Sec  Memory Limit: 128 MBSubmit: 101  Solved: 34[Submit][Status] Descr ...

随机推荐

  1. tcp异常断开的重连解决方法

    1.select超时重连 http://bbs.chinaunix.net/thread-4162149-1-1.html 2.http://bbs.csdn.net/topics/350074818 ...

  2. 网络入侵检测规避工具fragrouter

    网络入侵检测规避工具fragrouter   网络入侵检测系统可以通过拦截数据包,获取内容进而判断是否为恶意数据包.对于传输较大的数据包,通常会采用分片的方式,将大数据包拆分为小数据包进行传输.如果入 ...

  3. spring security 单一账户多地方登陆提醒, ajax 拦截器 Interceptor

    spring-security.xml部分代码: <http auto-config="false" > <access-denied-handler ref=& ...

  4. Canvas的效果操作及save()和restore()方法应用

    平移.缩放.旋转等操作等于是,我在一个正的画布绘制好图,然后再把画布做旋转.平移.缩放等等的效果. 也就是说,我使用的X.Y坐标还是正常的坐标(没旋转.平移.缩放等之前的坐标). save()和res ...

  5. MYSQL查询的四种情况

    1 普通连接查询 select 表1字段1,表2字段2,from 表1,表2,where 表1.字段1==表2.字段2 2 inner join查询 select 表1字段1 ,表2字段2,from ...

  6. 更新tensorflow支持GPU时出错

    sudo pip install --upgrade tensorflow-gpu Operation not permitted: '/tmp/pip-Sx_vMg-uninstall/System ...

  7. Spring 与 MyBatis 整合

    一.实验介绍 1.1 实验内容 本节课程将整合 Spring 和 MyBatis,并采用 Junit 进行单元测试. 1.2 实验知识点 Spring - MyBatis 整合 Junit 单元测试 ...

  8. Tyvj3308毒药解药题解

    题目大意 这些药都有可能在治愈某些病症的同一时候又使人患上某些别的病症--经过我天才的努力.最终弄清了每种药的详细性能,我会把每种药能治的病症和能使人患上的病症列一张清单给你们,然后你们要依据这张清单 ...

  9. 搭建windows下的odoo开发环境

    odoo运行环境的必须要要求是 python环境 postgreSQL数据 数据库可以安装在别的机器上,比如服务器:当然对于开发环境,通常,数据库与代码调试安装在同一台机器上. 首先安装 postgr ...

  10. 怎么设置MySQL就能让别人访问本机的数据库了?

    for all ips use below GRANT ALL PRIVILEGES ON *.* TO 'myuser'@'%' WITH GRANT OPTION; for particular ...