基本思路是将树形结构转线性结构,因为查询的是从任意结点到叶子结点的路径。
从而将每个查询转换成区间,表示从该结点到叶子结点的路径。
离线做,按照右边界升序排序。
利用树状数组区间修改。
树状数组表示有K个数据的数量,利用pos进行维护。
假设现有的sz >= K, 那么需要对区间进行修改。

  1. /* 4358 */
  2. #include <iostream>
  3. #include <sstream>
  4. #include <string>
  5. #include <map>
  6. #include <queue>
  7. #include <set>
  8. #include <stack>
  9. #include <vector>
  10. #include <deque>
  11. #include <algorithm>
  12. #include <cstdio>
  13. #include <cmath>
  14. #include <ctime>
  15. #include <cstring>
  16. #include <climits>
  17. #include <cctype>
  18. #include <cassert>
  19. #include <functional>
  20. #include <iterator>
  21. #include <iomanip>
  22. using namespace std;
  23. //#pragma comment(linker,"/STACK:102400000,1024000")
  24.  
  25. #define sti set<int>
  26. #define stpii set<pair<int, int> >
  27. #define mpii map<int,int>
  28. #define vi vector<int>
  29. #define pii pair<int,int>
  30. #define vpii vector<pair<int,int> >
  31. #define rep(i, a, n) for (int i=a;i<n;++i)
  32. #define per(i, a, n) for (int i=n-1;i>=a;--i)
  33. #define clr clear
  34. #define pb push_back
  35. #define mp make_pair
  36. #define fir first
  37. #define sec second
  38. #define all(x) (x).begin(),(x).end()
  39. #define SZ(x) ((int)(x).size())
  40. #define lson l, mid, rt<<1
  41. #define rson mid+1, r, rt<<1|1
  42.  
  43. typedef struct {
  44. int v, nxt;
  45. } edge_t;
  46.  
  47. typedef struct node_t {
  48. int w, id;
  49.  
  50. friend bool operator< (const node_t& a, const node_t& b) {
  51. if (a.w == b.w)
  52. return a.id < b.id;
  53. return a.w < b.w;
  54. }
  55.  
  56. } node_t;
  57.  
  58. typedef struct ques_t {
  59. int l, r, id;
  60. } ques_t;
  61.  
  62. const int maxn = 1e5+;
  63. const int maxv = maxn;
  64. const int maxe = maxv * ;
  65. int head[maxv], l;
  66. edge_t E[maxe];
  67. int Beg[maxn], End[maxn];
  68. int val[maxn], W[maxn];
  69. node_t nd[maxn];
  70. vi pvc[maxn];
  71. int dfs_clock;
  72. int n, K;
  73. int a[maxn];
  74. ques_t Q[maxn];
  75. int ans[maxn];
  76.  
  77. bool compq (const ques_t& a, const ques_t& b) {
  78. if (a.r == b.r)
  79. return a.l < b.l;
  80. return a.r < b.r;
  81. }
  82.  
  83. void init() {
  84. memset(head, -, sizeof(head));
  85. memset(a, , sizeof(a));
  86. dfs_clock = l = ;
  87. }
  88.  
  89. void addEdge(int u, int v) {
  90. E[l].v = v;
  91. E[l].nxt = head[u];
  92. head[u] = l++;
  93.  
  94. E[l].v = u;
  95. E[l].nxt = head[v];
  96. head[v] = l++;
  97. }
  98.  
  99. void dfs(int u, int fa) {
  100. int v, k;
  101.  
  102. Beg[u] = ++dfs_clock;
  103. val[dfs_clock] = W[u];
  104. for (k=head[u]; k!=-; k=E[k].nxt) {
  105. v = E[k].v;
  106. if (v == fa)
  107. continue;
  108. dfs(v, u);
  109. }
  110. End[u] = dfs_clock;
  111. }
  112.  
  113. int lowest(int x) {
  114. return x & -x;
  115. }
  116.  
  117. int sum(int x) {
  118. int ret = ;
  119.  
  120. while (x) {
  121. ret += a[x];
  122. x -= lowest(x);
  123. }
  124.  
  125. return ret;
  126. }
  127.  
  128. void update(int x, int delta) {
  129. while (x <= n) {
  130. a[x] += delta;
  131. x += lowest(x);
  132. }
  133. }
  134.  
  135. void solve() {
  136. int q;
  137. int u, v;
  138.  
  139. sort(nd+, nd++n);
  140. int cnt = ;
  141. W[nd[].id] = cnt;
  142. rep(i, , n+) {
  143. if (nd[i].w==nd[i-].w) {
  144. W[nd[i].id] = cnt;
  145. } else {
  146. W[nd[i].id] = ++cnt;
  147. }
  148. }
  149.  
  150. dfs(, );
  151.  
  152. rep(i, , cnt+) {
  153. pvc[i].clr();
  154. pvc[i].pb();
  155. }
  156.  
  157. scanf("%d", &q);
  158. rep(i, , q) {
  159. scanf("%d", &u);
  160. Q[i].l = Beg[u];
  161. Q[i].r = End[u];
  162. Q[i].id = i;
  163. }
  164.  
  165. sort(Q, Q+q, compq);
  166. int sz;
  167. int j = ;
  168.  
  169. rep(i, , n+) {
  170. pvc[val[i]].pb(i);
  171. sz = SZ(pvc[val[i]]) - ;
  172. if (sz >= K) {
  173. if (sz > K) {
  174. update(pvc[val[i]][sz-K-]+, -);
  175. update(pvc[val[i]][sz-K]+, );
  176. }
  177. update(pvc[val[i]][sz-K]+, );
  178. update(pvc[val[i]][sz-K+]+, -);
  179. }
  180. while (j<q && Q[j].r==i) {
  181. ans[Q[j].id] = sum(Q[j].l);
  182. ++j;
  183. }
  184. }
  185.  
  186. rep(i, , q)
  187. printf("%d\n", ans[i]);
  188. }
  189.  
  190. int main() {
  191. ios::sync_with_stdio(false);
  192. #ifndef ONLINE_JUDGE
  193. freopen("data.in", "r", stdin);
  194. freopen("data.out", "w", stdout);
  195. #endif
  196.  
  197. int t;
  198. int u, v;
  199.  
  200. scanf("%d", &t);
  201. rep(tt, , t+) {
  202. init();
  203. scanf("%d %d", &n, &K);
  204. rep(i, , n+) {
  205. scanf("%d", &W[i]);
  206. nd[i].id = i;
  207. nd[i].w = W[i];
  208. }
  209. rep(i, , n) {
  210. scanf("%d %d", &u, &v);
  211. addEdge(u, v);
  212. }
  213. printf("Case #%d:\n", tt);
  214. solve();
  215. if (tt != t)
  216. putchar('\n');
  217. }
  218.  
  219. #ifndef ONLINE_JUDGE
  220. printf("time = %d.\n", (int)clock());
  221. #endif
  222.  
  223. return ;
  224. }

数据发生器。

  1. from copy import deepcopy
  2. from random import randint, shuffle
  3. import shutil
  4. import string
  5.  
  6. def GenDataIn():
  7. with open("data.in", "w") as fout:
  8. t = 10
  9. bound = 10**9
  10. fout.write("%d\n" % (t))
  11. for tt in xrange(t):
  12. n = randint(100, 200)
  13. K = randint(1, 5)
  14. fout.write("%d %d\n" % (n, K))
  15. ust = [1]
  16. vst = range(2, n+1)
  17. L = []
  18. for i in xrange(n):
  19. x = randint(1, 100)
  20. L.append(x)
  21. fout.write(" ".join(map(str, L)) + "\n")
  22. for i in xrange(1, n):
  23. idx = randint(0, len(ust)-1)
  24. u = ust[idx]
  25. idx = randint(0, len(vst)-1)
  26. v = vst[idx]
  27. ust.append(v)
  28. vst.remove(v)
  29. fout.write("%d %d\n" % (u, v))
  30. q = n
  31. fout.write("%d\n" % (q))
  32. L = range(1, n+1)
  33. shuffle(L)
  34. fout.write("\n".join(map(str, L)) + "\n")
  35.  
  36. def MovDataIn():
  37. desFileName = "F:\eclipse_prj\workspace\hdoj\data.in"
  38. shutil.copyfile("data.in", desFileName)
  39.  
  40. if __name__ == "__main__":
  41. GenDataIn()
  42. MovDataIn()

【HDOJ】4358 Boring counting的更多相关文章

  1. 【HDOJ】3518 Boring Counting

    后缀数组2倍增可解. #include <cstdio> #include <cstring> #include <cstdlib> #define MAXN 10 ...

  2. 【HDOJ】P5056 Boring count

    题目意思是给你一个字符串和K,让你求其中有多少个字串中每个字母的出现次数不超过K次,可以等于 题目意思是很简单的,写起来也很简单,不过就是注意最后要是long long要不WA了,555~ #incl ...

  3. HDU 4358 Boring counting(莫队+DFS序+离散化)

    Boring counting Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 98304/98304 K (Java/Others) ...

  4. HDOJ 题目3518 Boring counting(后缀数组,求不重叠反复次数最少为2的子串种类数)

    Boring counting Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  5. HDU - 4358 Boring counting (dsu on tree)

    Boring counting: http://acm.hdu.edu.cn/showproblem.php?pid=4358 题意: 求一棵树上,每个节点的子节点中,同一颜色出现k次 的 个数. 思 ...

  6. hdu 4358 Boring counting dfs序+莫队+离散化

    Boring counting Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 98304/98304 K (Java/Others) ...

  7. 【BZOJ】4358: permu 莫队算法

    [题意]给定长度为n的排列,m次询问区间[L,R]的最长连续值域.n<=50000. [算法]莫队算法 [题解]考虑莫队维护增加一个数的信息:设up[x]表示数值x往上延伸的最大长度,down[ ...

  8. (好题)树状数组+离散化+DFS序+离线/莫队 HDOJ 4358 Boring counting

    题目传送门 题意:给你一棵树,树上的每个节点都有树值,给m个查询,问以每个点u为根的子树下有多少种权值恰好出现k次. 分析:首先要对权值离散化,然后要将树形转换为线形,配上图:.然后按照右端点从小到大 ...

  9. 【HDOJ】4729 An Easy Problem for Elfness

    其实是求树上的路径间的数据第K大的题目.果断主席树 + LCA.初始流量是这条路径上的最小值.若a<=b,显然直接为s->t建立pipe可以使流量最优:否则,对[0, 10**4]二分得到 ...

随机推荐

  1. NHibernate各种查询

    NHibernate各种查询 NHibernate's methods of querying are powerful, but there's a learning curve. Longer t ...

  2. Java调用CMD命令

    java的Runtime.getRuntime().exec(commandStr)可以调用执行cmd指令. cmd /c dir 是执行完dir命令后关闭命令窗口. cmd /k dir 是执行完d ...

  3. DTCMS自定义标签:获取所有栏目以及不显示指定栏目

    DTcms.Web.UI\Label\category.cs中 添加下面代码 /// <summary> /// 返回所有类别 /// </summary> /// <r ...

  4. 【转】Qt使用自带的windeployqt 生成exe来发布软件

    集成开发环境 QtCreator 目前生成图形界面程序 exe 大致可以分为两类:Qt Widgets Application  和 Qt Quick Application.下面分别介绍这两类exe ...

  5. Spark Streaming揭秘 Day12 数据安全容错(Executor篇)

    Spark Streaming揭秘 Day12 数据安全容错(Executor篇) 今天,让我们研究下SparkStreaming在Executor端的数据安全及容错机制. 在SparkStreami ...

  6. 《C和指针》 读书笔记 -- 第8章 数组

    1.在C中,数组名的值是一个指针常量而不是指针变量,也就是数组第一个元素的地址. 2.数组和指针的区别: 声明一个数组时,编译器将根据声明所指定的元素数量为数组保留内存空间,然后再创建数组名,它的值是 ...

  7. xaml中绑定单例属性

    在项目中经常会遇到,同一个字典表绑定到多个ItemsControl上的情况,可以在单例中创建一个List,xaml上绑定即可.看代码: 1,XAML <Grid> <StackPan ...

  8. size()函数的使用

    matlab中对于矩阵的计算是十分方便的,其中关于矩阵的函数有很多 size() 在c/c++中sizeof用来求某变量所占用的字节数,在matlab中size()则可以用来求矩阵的“长度”,矩阵的长 ...

  9. Oracle监听器—动态注册

    注册就是将数据库作为一个服务注册到监听程序.客户端不需要知道数据库名和实例名,只需要知道该数据库对外提供的服务名就可以申请连接到数据库.这个服务名可能与实例名一样,也有可能不一样. 注册分: 1. 静 ...

  10. Kinetic使用注意点--lable

    new Lable(config) 参数: config:包含所有配置项的对象. { x: "横坐标", y: "纵坐标", width: "宽度&q ...