看了题解那个弱化版后,马上就去做了HDU 3333这道题,发现有可用的地方。于是往这方面想,主要是处理如何确定一个数出现K次的问题。想到了从左往右把每个数出现的次数记下来,但感觉不是这样,呃,再看别人做的,真的是这样的--!

主要是处理一个数出现K次后的情况,把每个数出现的位置记录下来,当出现大于等于K次时,假设此时已出现sz个,则把sz-k这个位置加1,把之前的SZ-K-1的位置-2,使之状态是-1(因为之前刚好出现K次时就已加1)。于是当查询到右端点时,求出区间和,+1和-1刚好消去。需要注意的是,当SZ-K-2>=0时,应当把SZ-K-2之前为-1的位置置成0,即加1。这样结果才是正确的。

至于把树映射到数组,很简单,使用DFS+时间戳的方法就可以了,记录每个结点第一次出现的次序以及深搜完以该结点为根的子树的最后一个时间戳即可。

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <algorithm>
  5. #include <cmath>
  6. #include <map>
  7. #include <vector>
  8. #define LL __int64
  9. #define lowbit(x) ((x)&(-x))
  10. using namespace std;
  11.  
  12. const int N=100100;
  13. const int Q=100100;
  14.  
  15. struct Query{
  16. int l,r,Id;
  17. Query(){}
  18. Query(int ll,int rr,int d){
  19. l=ll; r=rr; Id=d;
  20. }
  21. bool operator <(const Query &a)const{
  22. if(r<a.r) return true;
  23. return false;
  24. }
  25. };
  26. Query query[Q];
  27. LL su[N],ans[Q];
  28. int num[N],val[N];
  29. struct Node{
  30. int bgn,en;
  31. };
  32. Node node[N];
  33. vector<int>pos[N];
  34. int n,k,q,tot,DEP;
  35.  
  36. struct Edge{
  37. int u,v,next;
  38. }edge[N*2];
  39. int head[N];
  40.  
  41. void addedge(int u,int v){
  42. edge[tot].u=u;
  43. edge[tot].v=v;
  44. edge[tot].next=head[u];
  45. head[u]=tot++;
  46. }
  47.  
  48. LL sum(int x){
  49. if(x==0) return 0;
  50. LL s=0;
  51. for(;x;x-=lowbit(x)){
  52. s+=su[x];
  53. }
  54. return s;
  55. }
  56.  
  57. void update(int x,LL w){
  58. for(;x<=n;x+=lowbit(x))
  59. su[x]+=w;
  60. }
  61.  
  62. void dfs(int u,int f){
  63. ++DEP;
  64. node[u].bgn=DEP;
  65. val[DEP]=num[u];
  66. for(int e=head[u];e!=-1;e=edge[e].next){
  67. int v=edge[e].v;
  68. if(v!=f){
  69. dfs(v,u);
  70. }
  71. }
  72. node[u].en=DEP;
  73. }
  74.  
  75. int main(){
  76. int T,t=0,u,v,cnt=0;
  77. scanf("%d",&T);
  78. while(++t<=T){
  79. map<int,int>mp;
  80. tot=0;DEP=0;
  81. cnt=0;
  82. scanf("%d%d",&n,&k);
  83. for(int i=1;i<=n;i++){
  84. scanf("%d",&num[i]);
  85. head[i]=-1;
  86. su[i]=0;
  87. pos[i].clear();
  88. if(!mp[num[i]])
  89. mp[num[i]]=++cnt;
  90. }
  91. for(int i=1;i<n;i++){
  92. scanf("%d%d",&u,&v);
  93. addedge(u,v);
  94. addedge(v,u);
  95. }
  96. dfs(1,0);
  97. scanf("%d",&q);
  98. for(int i=1;i<=q;i++){
  99. scanf("%d",&cnt);
  100. query[i]=Query(node[cnt].bgn,node[cnt].en,i);
  101. }
  102. sort(query+1,query+1+q);
  103. cnt=1;
  104. int sz;
  105. for(int i=1;i<=n;i++){
  106. int t=mp[val[i]];
  107. pos[t].push_back(i);
  108. sz=pos[t].size();
  109. if(sz>=k){
  110. if(sz==k){
  111. update(pos[t][sz-k],1);
  112. }
  113. else{
  114. update(pos[t][sz-k-1],-2);
  115. update(pos[t][sz-k],1);
  116. }
  117. if(sz-k-2>=0)
  118. update(pos[t][sz-k-2],1);
  119. }
  120. while(query[cnt].r==i){
  121. ans[query[cnt].Id]=sum(query[cnt].r)-sum(query[cnt].l-1);
  122. cnt++;
  123. }
  124. }
  125. printf("Case #%d:\n",t);
  126. for(int i=1;i<=q;i++)
  127. printf("%I64d\n",ans[i]);
  128. if(t<T)
  129. puts("");
  130. }
  131. return 0;
  132. }

  

HDU 4358的更多相关文章

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

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

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

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

  3. hdu 4358 Boring counting 离散化+dfs序+莫队算法

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4358 题意:以1为根节点含有N(N <= 1e5)个结点的树,每个节点有一个权值(weight ...

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

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

  5. HDU 4358 莫队算法+dfs序+离散化

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

  6. HDU 4358 Boring counting 树状数组+思路

    研究了整整一天orz……直接上官方题解神思路 #include <cstdio> #include <cstring> #include <cstdlib> #in ...

  7. HDU 4358 Boring counting dfs序+莫队算法

    题意:N个节点的有根树,每个节点有一个weight.有Q个查询,问在以u为根的子树中,有恰好出现了K次的weight有多少种. 这是第一次写莫队算法,之前也只是偶有耳闻. 看了别人的代码打的,还是贴上 ...

  8. HDU - 4358 Boring counting (树上启发式合并/线段树合并)

    题目链接 题意:统计树上每个结点中恰好出现了k次的颜色数. dsu on tree/线段树合并裸题. 启发式合并1:(748ms) #include<bits/stdc++.h> usin ...

  9. ACM数据结构相关资料整理【未完成,待补充】

    在网上总是查不到很系统的练ACM需要学习的数据结构资料,于是参考看过的东西,自己整理了一份. 能力有限,欢迎大家指正补充. 分类主要参考<算法竞赛入门经典训练指南>(刘汝佳),山东大学数据 ...

随机推荐

  1. Date and time types

    https://docs.microsoft.com/en-us/sql/t-sql/data-types/date-and-time-types date (Transact-SQL)datetim ...

  2. python 数据的基本类型(字符串)

    python 基础 ascii:字母,数字,特殊字符:1个字节(byte) 8个字位(bit)unicode: 16位两个字节,升级32个字节 4个字位utf-8:最少一个字节 8个表示. 英文 8字 ...

  3. springsecurity+jwt实践和学习

    1.参考资料: https://blog.csdn.net/qq924862077/article/details/83038031 https://blog.csdn.net/sxdtzhaoxin ...

  4. Hadoop MapReduce编程 API入门系列之wordcount版本1(五)

    这个很简单哈,编程的版本很多种. 代码版本1 package zhouls.bigdata.myMapReduce.wordcount5; import java.io.IOException; im ...

  5. IOS-UITextField-改变光标颜色

    方法1: [[UITextField appearance] setTintColor:[UIColor blackColor]]; 这种方法将影响所有TextField. 方法2: textFiel ...

  6. BZOJ1060: [ZJOI2007]时态同步(树形dp 贪心)

    Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3285  Solved: 1286[Submit][Status][Discuss] Descript ...

  7. 树的问题小结(最小生成树、次小生成树、最小树形图、LCA、最小支配集、最小点覆盖、最大独立集)

    树的定义:连通无回路的无向图是一棵树. 有关树的问题: 1.最小生成树. 2.次小生成树. 3.有向图的最小树形图. 4.LCA(树上两点的最近公共祖先). 5.树的最小支配集.最小点覆盖.最大独立集 ...

  8. C++的Matlab接口

    与 原文 过程有些不同,根据具体环境自行配置即可! 转自于:http://blog.csdn.net/left_la/article/details/8206645 我的计算机环境是win7 64位系 ...

  9. SQL的类型转换

    说到SQL类型转换,我们知道SQL是一个弱类型语言,所以可以做隐式的强制类型转换,下面记录一下这几天遇到的类型转换问题. 1.在SQL中,字符串类型与数字之间转换是不需要强制类型转换符的,如果字符串是 ...

  10. (转)shiro权限框架详解06-shiro与web项目整合(下)

    http://blog.csdn.net/facekbook/article/details/54962975 shiro和web项目整合,实现类似真实项目的应用 web项目中认证 web项目中授权 ...