看了题解那个弱化版后,马上就去做了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+时间戳的方法就可以了,记录每个结点第一次出现的次序以及深搜完以该结点为根的子树的最后一个时间戳即可。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <map>
#include <vector>
#define LL __int64
#define lowbit(x) ((x)&(-x))
using namespace std; const int N=100100;
const int Q=100100; struct Query{
int l,r,Id;
Query(){}
Query(int ll,int rr,int d){
l=ll; r=rr; Id=d;
}
bool operator <(const Query &a)const{
if(r<a.r) return true;
return false;
}
};
Query query[Q];
LL su[N],ans[Q];
int num[N],val[N];
struct Node{
int bgn,en;
};
Node node[N];
vector<int>pos[N];
int n,k,q,tot,DEP; struct Edge{
int u,v,next;
}edge[N*2];
int head[N]; void addedge(int u,int v){
edge[tot].u=u;
edge[tot].v=v;
edge[tot].next=head[u];
head[u]=tot++;
} LL sum(int x){
if(x==0) return 0;
LL s=0;
for(;x;x-=lowbit(x)){
s+=su[x];
}
return s;
} void update(int x,LL w){
for(;x<=n;x+=lowbit(x))
su[x]+=w;
} void dfs(int u,int f){
++DEP;
node[u].bgn=DEP;
val[DEP]=num[u];
for(int e=head[u];e!=-1;e=edge[e].next){
int v=edge[e].v;
if(v!=f){
dfs(v,u);
}
}
node[u].en=DEP;
} int main(){
int T,t=0,u,v,cnt=0;
scanf("%d",&T);
while(++t<=T){
map<int,int>mp;
tot=0;DEP=0;
cnt=0;
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++){
scanf("%d",&num[i]);
head[i]=-1;
su[i]=0;
pos[i].clear();
if(!mp[num[i]])
mp[num[i]]=++cnt;
}
for(int i=1;i<n;i++){
scanf("%d%d",&u,&v);
addedge(u,v);
addedge(v,u);
}
dfs(1,0);
scanf("%d",&q);
for(int i=1;i<=q;i++){
scanf("%d",&cnt);
query[i]=Query(node[cnt].bgn,node[cnt].en,i);
}
sort(query+1,query+1+q);
cnt=1;
int sz;
for(int i=1;i<=n;i++){
int t=mp[val[i]];
pos[t].push_back(i);
sz=pos[t].size();
if(sz>=k){
if(sz==k){
update(pos[t][sz-k],1);
}
else{
update(pos[t][sz-k-1],-2);
update(pos[t][sz-k],1);
}
if(sz-k-2>=0)
update(pos[t][sz-k-2],1);
}
while(query[cnt].r==i){
ans[query[cnt].Id]=sum(query[cnt].r)-sum(query[cnt].l-1);
cnt++;
}
}
printf("Case #%d:\n",t);
for(int i=1;i<=q;i++)
printf("%I64d\n",ans[i]);
if(t<T)
puts("");
}
return 0;
}

  

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. 国产芯片任重道远 国科微SSD主控芯片的“追赶之路”(不能只提供一颗芯片,而是要将芯片、国密算法、固件Firmware、BIOS和操作系统紧密联系在一起,变成完整解决方案交给行业用户,才能真正体现自身的价值)

    集微网消息,“中国芯”战略之路道阻且长,踏入这个赛道的攻坚者们需要十年如一日的技术突破,需要集合产业势能,共同协作,方能建立中国核心技术真正的竞争力. 国产化之路任重道远,SSD芯片初见成效 信息时代 ...

  2. oc16--set,get

    // // Kline.h // day13 #import <Foundation/Foundation.h> @interface Kline : NSObject { int _ma ...

  3. C#关于XML的一些简单用法

    关于XML文件的用法,本文简单介绍创建.读取和增删操作 . 1.创建有三种方法 (1)通过XmlDocument创建,然后分级添加子目录 XmlDocument doc = new XmlDocume ...

  4. Windows显示我的电脑到桌面以及给一些程序设置快捷键

    Windows显示我的电脑到桌面,我测试的是windows server 2012和windows10  1.按Win(键盘上的微软徽标键)+R,输入: rundll32.exe shell32.dl ...

  5. 10.2&10.3 Xcode开发包

    10.2开发包下载链接 10.3开发包下载链接 Finder打开后,按command+shift+G前往这个地址: /Applications/Xcode.app/Contents/Developer ...

  6. Vue.js 2 vs Vue.js 3的实现 – 云栖社区

    Vue.js 2 vs Vue.js 3的实现 – 云栖社区 vue.js核心团队已经讨论过将在Vue3实现的变化.虽然API不会改变,但是数据响应机制(译者注:对数据改变的监听和通知)发生了变化.这 ...

  7. 代码实现wordpress彩色标签云的最简单的方法

    首先在wordpress主题文件夹内找到并用编辑器打开 functions.php 文件,随意找个位置不到插到别的函数里,“?>” 之前加入以下代码: //彩色标签云 function colo ...

  8. 读书笔记「Python编程:从入门到实践」_2.变量和简单数据类型

    做了大半年RPA了,用的工具是Kapow. 工作没有那么忙,不想就这么荒废着,想学点什么.就Python吧. 为期三个月,希望能坚持下来. 2.1 变量的命名和使用 变量名只能包含字母.数字和下划线. ...

  9. java必备技能

    Android应用程序开发是以Java语言为基础的,所以需要有扎实的Java基础知识.首先熟悉java基本语法,然后熟悉设计模式等. a) Java基础语法:看下面的<Java知识点列表> ...

  10. 关于ZBrush中Subtool的小秘密

    想问大家一个问题,你们刚开始学习ZBrush 3D图形绘制软件的时候,是不是特别迷茫?有没有人和小编一样,一直以为ZBrush中的Subtools就相当于Layers呢? 经过长时间的实践之后,小编才 ...