HDU 4358
看了题解那个弱化版后,马上就去做了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的更多相关文章
- HDU 4358 Boring counting(莫队+DFS序+离散化)
Boring counting Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 98304/98304 K (Java/Others) ...
- HDU - 4358 Boring counting (dsu on tree)
Boring counting: http://acm.hdu.edu.cn/showproblem.php?pid=4358 题意: 求一棵树上,每个节点的子节点中,同一颜色出现k次 的 个数. 思 ...
- hdu 4358 Boring counting 离散化+dfs序+莫队算法
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4358 题意:以1为根节点含有N(N <= 1e5)个结点的树,每个节点有一个权值(weight ...
- hdu 4358 Boring counting dfs序+莫队+离散化
Boring counting Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 98304/98304 K (Java/Others) ...
- HDU 4358 莫队算法+dfs序+离散化
Boring counting Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 98304/98304 K (Java/Others)T ...
- HDU 4358 Boring counting 树状数组+思路
研究了整整一天orz……直接上官方题解神思路 #include <cstdio> #include <cstring> #include <cstdlib> #in ...
- HDU 4358 Boring counting dfs序+莫队算法
题意:N个节点的有根树,每个节点有一个weight.有Q个查询,问在以u为根的子树中,有恰好出现了K次的weight有多少种. 这是第一次写莫队算法,之前也只是偶有耳闻. 看了别人的代码打的,还是贴上 ...
- HDU - 4358 Boring counting (树上启发式合并/线段树合并)
题目链接 题意:统计树上每个结点中恰好出现了k次的颜色数. dsu on tree/线段树合并裸题. 启发式合并1:(748ms) #include<bits/stdc++.h> usin ...
- ACM数据结构相关资料整理【未完成,待补充】
在网上总是查不到很系统的练ACM需要学习的数据结构资料,于是参考看过的东西,自己整理了一份. 能力有限,欢迎大家指正补充. 分类主要参考<算法竞赛入门经典训练指南>(刘汝佳),山东大学数据 ...
随机推荐
- GNU TeXmacs 1.99.8 发布,所见即所得科学编辑器(看看老实的GUI)
GNU TeXmacs 1.99.8 已发布,这是一个支持各种数学公式的所见即所得编辑器,可以用来编辑文本.图形.数学.交互内容,它的界面非常友好,并且内置高质量的排版引擎. 更新内容: bug 修复 ...
- Sublime Text 2 界面主题 推荐 Flatland
先搜索下THEME-FLATLAND 安装完后在preferences中选择settings-usr { "color_scheme": "Packages/Theme ...
- Node.js:事件循环
ylbtech-Node.js:事件循环 1.返回顶部 1. Node.js 事件循环 Node.js 是单进程单线程应用程序,但是通过事件和回调支持并发,所以性能非常高. Node.js 的每一个 ...
- VMware 安装LINUX系统(一)
我用的是WORKSTATION 15 PRO https://www.vmware.com/asean/products/workstation-pro/ 1.安装LINUX 打开Vmware,点击创 ...
- oracle连接数不够解决
ora-12516: TNS: 监听程序找不到符合协议堆栈要求的可用处理程 看到如上错误出现,就要查看是否是是数据库连接数被占满了 具体的查询sql如下: select count(*) from v ...
- docker(三):Harbor 1.8.0 仓库的安装和使用
回顾: docker(一):docker是什么? docker(二):CentOS安装docker docker(部署常见应用):docker部署mysql 安装的先决条件 硬件环境 1.CPU ...
- Liunx搜索命令行
1.grep grep(General Regular Expression Parser,通用规则表达式分析程序)是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印出来. 它的使 ...
- udacity_javascript设计模式
javascript设计模式 的学习记录 在优达学城上找到的 <javascript设计模式> 他主要是带动我们的思考 在 <第二章 分离重构> 中使用了 model octo ...
- Web移动端常见问题
一.按钮点击时出现黑色背景 解决方法: .class { -webkit-tap-highlight-color:rgba(0,0,0,0);} .class { -webkit-appearance ...
- 数据结构——栈的实现(数组、Java)
巩固数据结构 栈是一种有限制的线性表 只能对表尾进行操作 package com.shine.test.datastruct; import java.util.Arrays; public clas ...