Codeforces 375D 数据结构(好题中的好题, 4解)
2014-03-25 19:38
211 查看
题目链接:http://codeforces.com/problemset/problem/375/D
全部代码:https://github.com/9974/DataStructures/tree/master/375D
题意:给你一棵树n个点,m次询问(n=100000,m=100000),每个节点有一种颜色,
每次询问问你以v节点为根的子树中 满足 同一种颜色的个数>=k的 颜色有几个。
方法1:显然询问要离线处理,不妨用思维简单的分块算法处理询问,
对于每个询问,我们用数组val[i]表示当前情况下 颜色为i的节点个数
再用val[i]当做下标,用数状数组维护个数的后缀和,
每次修改一个点 树状数组里面更新2次, 总体复杂度O(sqrt(n)*n*log(n));
方法2:
其实也算方法1的优化, 不同之处只是用一个数组维护后缀和,
我们发现 每次修改无非就是把val[i]加一或者减一,不妨用数组sum表示要求的答案
加1:唯一改变的是 val[i]+1的答案, 这个答案要加1, 即sum[++val[i]]++;
减1:唯一改变的是 val[i]的答案, 这个答案要减1, 即sum[val[i]--]--;
总体复杂度O(sqrt(n)*n);
方法3:启发式合并, 询问按节点v分类,从叶子节点不断合并,注意这里一定要把小的堆合并到大的堆里面,
每个子树用一个平衡树维护(这里我用了treap),用另外一个平衡树维护每个节点u为根的子树的所有颜色个数
(我用了map)合并过程就是把两棵平衡树合并, treap里面维护的是val[i],要求答案只要算一下后缀和就可以了
总体复杂度O(n*log^2(n))
方法4: 分治思想, 同样询问按节点v分类, 想想暴力的做法处理询问,用一个全局的数组维护答案,发现O(n^2)可做
但是会超时, 我们可以做个优化, 对于根u 处理 其子树v1,v2,v3....时, 我们算子树答案的时候,
把v1子树放到答案数组里, 算完以后清空v1子树, 然后在重复v2,v3....., 注意到最后一个子树没有必要清空,
算完最后一个v后dfs会回溯到上一层,去算上一层的答案,而上一层一定包含了v子树, 清空了反而复杂度会大大提升,
所以我们当然是把子树规模最大的放到最后去处理比较优秀,这里类似熟练剖分的重链,
每次把子树加进来和删除另外写两个dfs暴力加减,这样平均下来每个点被添加和删除的次数就不会超过log(n),
这样一来总体复杂度为O(n*log(n))
全部代码:https://github.com/9974/DataStructures/tree/master/375D
题意:给你一棵树n个点,m次询问(n=100000,m=100000),每个节点有一种颜色,
每次询问问你以v节点为根的子树中 满足 同一种颜色的个数>=k的 颜色有几个。
方法1:显然询问要离线处理,不妨用思维简单的分块算法处理询问,
对于每个询问,我们用数组val[i]表示当前情况下 颜色为i的节点个数
再用val[i]当做下标,用数状数组维护个数的后缀和,
每次修改一个点 树状数组里面更新2次, 总体复杂度O(sqrt(n)*n*log(n));
方法2:
其实也算方法1的优化, 不同之处只是用一个数组维护后缀和,
我们发现 每次修改无非就是把val[i]加一或者减一,不妨用数组sum表示要求的答案
加1:唯一改变的是 val[i]+1的答案, 这个答案要加1, 即sum[++val[i]]++;
减1:唯一改变的是 val[i]的答案, 这个答案要减1, 即sum[val[i]--]--;
总体复杂度O(sqrt(n)*n);
方法3:启发式合并, 询问按节点v分类,从叶子节点不断合并,注意这里一定要把小的堆合并到大的堆里面,
每个子树用一个平衡树维护(这里我用了treap),用另外一个平衡树维护每个节点u为根的子树的所有颜色个数
(我用了map)合并过程就是把两棵平衡树合并, treap里面维护的是val[i],要求答案只要算一下后缀和就可以了
总体复杂度O(n*log^2(n))
方法4: 分治思想, 同样询问按节点v分类, 想想暴力的做法处理询问,用一个全局的数组维护答案,发现O(n^2)可做
但是会超时, 我们可以做个优化, 对于根u 处理 其子树v1,v2,v3....时, 我们算子树答案的时候,
把v1子树放到答案数组里, 算完以后清空v1子树, 然后在重复v2,v3....., 注意到最后一个子树没有必要清空,
算完最后一个v后dfs会回溯到上一层,去算上一层的答案,而上一层一定包含了v子树, 清空了反而复杂度会大大提升,
所以我们当然是把子树规模最大的放到最后去处理比较优秀,这里类似熟练剖分的重链,
每次把子树加进来和删除另外写两个dfs暴力加减,这样平均下来每个点被添加和删除的次数就不会超过log(n),
这样一来总体复杂度为O(n*log(n))
相关文章推荐
- codeforces 501D Misha and Permutations Summation(康拓展开+数据结构)
- 第三周周赛——基础数据结构结业场(坚持就会有AK,题目出自codeforces 633C,633D,631B,651A,651C以及poj1577)
- CodeForces - 799B T-shirt buying 数据结构
- The Union of k-Segments CodeForces - 612D 什么技巧还有数据结构
- CodeForces - 675D Tree Construction (set&数据结构)
- CodeForces 546C Soldier and Cards(数据结构模拟)
- codeforces 748D Santa Claus and a Palindrome (构造+贪心+数据结构)
- codeforces-375D-树上莫队
- Codeforces 31C Schedule(数据结构)
- 【codeforces 813E】【Army Creation】【数据结构】
- codeforces 804B——Ice cream coloring(图论,dfs,数据结构,好题)
- codeforces 173E 数据结构 好题
- 【Codeforces 722C】Destroying Array (数据结构、set)
- CodeForces - 375B (dp)(数据结构)
- Codeforces 922 C - Robot Vacuum Cleaner (贪心、数据结构、sort中的cmp)
- [Codeforces 940.E] Cashback(dp,数据结构,贪心)
- CodeForces 140C - New Year Snowmen(数据结构)
- codeforces 283A - Cows and Sequence 简单数据结构模拟
- CodeForces 339D Xenia and Bit Operations 数据结构+线段树+点更新
- CodeForces 337D——Book of Evil(数据结构)