Gty的妹子树
Posted on 2015年1月17日 17:04/****************************************\ * Author : ztx * Title : bzoj 3720 Gty的妹子树 * ALG : 分块 * CMT : * 我们用一次dfs过程将树分块. * 首先, 定义根节点在块1中, 块1的size为1. * 从根节点向下dfs, 对于当前点x, 依次遍历其儿子, 若遍历到儿子son时x所在的块的size小于Maxsize, 则将son加入x所在的块, x所在的块的size+1. * 否则, 建立一个新块, 使son加入这个新块, 新块的size+1. * 每遍历到一个儿子就向下dfs. * * 然后我们记录两个图, 一个是原来的树, 一个是块与块之间形成的图, 只需要在每次产生新块的时候加一条边即可. * 不难发现, 块与块之间事实上形成的也是树形结构. * 我们再对于每一个块记录下块内所有的权值, 并排序. * * 对于询问, 我们从当前节点向下dfs: * 1.若遇到一个儿子不属于其所在的块, 则转到块与块之间形成的树向下搜索, 每遇到一个块就在块里二分找答案. * 2.如果儿子依旧属于这个块, 那就直接看一下他和x的大小关系即可. * 若令 Maxsize = sqrt(n), 这样的复杂度是O(sqrt(n)log(sqrt(n))). * 对于加入新点, 我们直接在其父亲所在的块中加入一个点即可, 需要暴力修改权值的有序序列, 复杂度O(sqrt(n)). * 当然如果父亲所在的块size达到了MAxsize, 就新建一个一个点的新块. * 如果修改权值, 就直接在这个点所在的块的权值序列中暴力删除, 插入即可, 时间复杂度O(sqrt(n)). * Time : \****************************************/
/****************************************\ * Author : ztx * Title : bzoj 3720 Gty的妹子树 * ALG : 分块 * CMT : * 我们用一次dfs过程将树分块. * 首先, 定义根节点在块1中, 块1的size为1. * 从根节点向下dfs, 对于当前点x, 依次遍历其儿子, 若遍历到儿子son时x所在的块的size小于Maxsize, 则将son加入x所在的块, x所在的块的size+1. * 否则, 建立一个新块, 使son加入这个新块, 新块的size+1. * 每遍历到一个儿子就向下dfs. * * 然后我们记录两个图, 一个是原来的树, 一个是块与块之间形成的图, 只需要在每次产生新块的时候加一条边即可. * 不难发现, 块与块之间事实上形成的也是树形结构. * 我们再对于每一个块记录下块内所有的权值, 并排序. * * 对于询问, 我们从当前节点向下dfs: * 1.若遇到一个儿子不属于其所在的块, 则转到块与块之间形成的树向下搜索, 每遇到一个块就在块里二分找答案. * 2.如果儿子依旧属于这个块, 那就直接看一下他和x的大小关系即可. * 若令 Maxsize = sqrt(n), 这样的复杂度是O(sqrt(n)log(sqrt(n))). * 对于加入新点, 我们直接在其父亲所在的块中加入一个点即可, 需要暴力修改权值的有序序列, 复杂度O(sqrt(n)). * 当然如果父亲所在的块size达到了MAxsize, 就新建一个一个点的新块. * 如果修改权值, 就直接在这个点所在的块的权值序列中暴力删除, 插入即可, 时间复杂度O(sqrt(n)). * Time : \****************************************/ #include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <algorithm> using namespace std ; #define maxn 60010LL #define masz 210LL int n , fa[maxn] = {0} ; int data[maxn] , belong[maxn] , blccnt = 0 ; int blc[maxn][masz] , siz[maxn] = {0} , blcsiz = 0 ; vector<int> G[maxn] , Bc[maxn] ; void Dfs(int u , int tp) { int i ; int from = belong[u] ; blc[from][++siz[from]] = data[u] ; fa[u] = tp ; for (i = 0 ; i < G[u].size() ; i ++ ) if (G[u][i] != tp) { if (siz[from] < blcsiz) belong[G[u][i]] = from ; else { belong[G[u][i]] = ++blccnt ; Bc[from].push_back(blccnt); } Dfs(G[u][i] , u) ; } } int Find(int u , int w) { int tmp = upper_bound(blc[u]+1 , blc[u]+siz[u]+1 , w)-blc[u]-1 ; return siz[u]-tmp ; } int QueryBlc(int u , int w) { int i ; int ret = Find(u , w) ; for (i = 0 ; i < Bc[u].size() ; i ++ ) ret += QueryBlc(Bc[u][i] , w) ; return ret ; } int Query(int u , int tp , int w) { int i ; int ret = data[u]>w ? 1 : 0 ; for (i = 0 ; i < G[u].size() ; i ++ ) if (G[u][i] != tp) { if (belong[G[u][i]] == belong[u]) ret += Query(G[u][i] , u , w) ; else ret += QueryBlc(belong[G[u][i]] , w) ; } return ret ; } void Insert(int tp , int w) { int from = belong[tp] ; fa[++n] = tp , data[n] = w ; G[tp].push_back(n) , G[n].push_back(tp) ; if (siz[from] < blcsiz) { blc[belong[n] = from][++siz[from]] = data[n] ; sort(blc[from]+1 , blc[from]+siz[from]+1) ; } else { Bc[from].push_back(belong[n] = ++blccnt) ; blc[blccnt][++siz[blccnt]] = data[n] ; } } void Change(int u , int w) { int i ; int from = belong[u] ; for (i = 1 ; i <= siz[from] ; i ++ ) if (blc[from][i] == data[u]) { blc[from][i] = data[u] = w ; break ; } sort(blc[from]+1 , blc[from]+siz[from]+1) ; } void BuildBlc() { int from ; blcsiz = (int)sqrt(n+0.5+log(n)/log(2)) ; belong[1] = ++blccnt ; Dfs(1 , 0) ; for (from = 1 ; from <= blccnt ; from ++ ) sort(blc[from]+1 , blc[from]+siz[from]+1) ; } int main() { int i , u , v , m , cmd , LAST = 0 ; // #define READ #ifdef READ freopen(".in" ,"r",stdin ) ; freopen(".out","w",stdout) ; #endif scanf("%d", &n) ; for (i = 1 ; i < n ; i ++ ) { scanf("%d%d", &u , &v) ; G[u].push_back(v) , G[v].push_back(u) ; } for (u = 1 ; u <= n ; u ++ ) scanf("%d", &data[u]) ; BuildBlc() ; scanf("%d", &m) ; for (i = 1 ; i <= m ; i ++ ) { scanf("%d%d%d", &cmd , &u , &v) ; u ^= LAST , v ^= LAST ; if (cmd == 0) printf("%d\n", LAST = Query(u , fa[u] , v)) ; else if (cmd == 1) Change(u , v) ; else Insert(u , v) ; } #ifdef READ fclose(stdin) ; fclose(stdout) ; #else getchar() ; getchar() ; #endif return 0 ; }