点此看题

简要题面

一棵树上有n个节点,每个节点有对应的名字(名字可重复)。

每次询问,求深度比$vi$多$ki$的$vi$的儿子中,有多少种名字

分析

Step1:

我们可以懂$DFS$轻松找到每个节点的深度dep[x], 同时用$DFS$序列得知每个节点间的关系(也就是说,可以用in[x]与ou[x],来知道另一个节点$v$是不是$x$的儿子)。

做完以上工作,本题所求的结果即是 已知深度dep,求in[x]在in[father]~ou[father]中的$x$,他们名字共有多少种

Stepp:

要求一段区间中不同的种类,我们可以联想到 **HH的项链** [https://www.luogu.com.cn/problem/P1972] (点此进入)

我们可以用很多方法来完成这道题,像**莫队、主席树、树状数组等** 这道题我用的是树状数组 先贴一个HH的项链的code吧

#include<bits/stdc++.h>
using namespace std;
#define re register int
const int N=1e6+5;
int n, m, a[N], c[N];
inline int lowbit(const int x) {return x&-x;}
inline int getsum(const int x)
{
int ret=0;
for(re i=x;i > 0;i-=lowbit(i)) ret += c[i];
return ret;
}
inline void modi(const int x,const int d)
{
for(re i=x;i<=1000000;i+=lowbit(i)) c[i] += d;
}
struct node{
int a, b, id;
bool operator<(const node&x)const{
return x.b > b; // 右端点从小到大排序
}
}ask[N];
int lst[N], ans[N]; // lst[i]表示 颜色i最近一次出现的位置
signed main()
{
scanf("%d",&n);
for(re i=1;i<=n;++i) scanf("%d",&a[i]);
scanf("%d",&m);
for(re i=1;i<=m;++i)
{
scanf("%d%d",&ask[i].a,&ask[i].b);
ask[i].id = i;
}
sort(ask+1, ask+1+m); // 将询问区间 由右端点从小到大 排序
for(re i=1, k=1;i<=n && k<=m;++i)
{
modi(i, 1); // 每次到一个新的点,将区间[i,n] +1
if(lst[a[i]]) modi(lst[a[i]], -1);
// 如果之前已经有过这个颜色 ,将曾经的颜色位置 -1
// 正确性:我们已经将询问排了序,所以以后的询问只需要离右端点近的颜色
lst[a[i]] = i;
while(k <= m && ask[k].b == i)
{
ans[ask[k].id] = getsum(i)- getsum(ask[k].a-1); // 注意减一
k++;
}
}
for(re i=1;i<=m;++i) printf("%d\n", ans[i]);
}

 该题代码

#include<bits/stdc++.h>
using namespace std;
#define re register int
const int N=1e6+5, M=4e6;
map<string, int>mp;
vector<int>V[N];
int n, total, in[N], ou[N], dep[N];
int tt, las[N], nt[M], ed[M], bel[N], maxdep;
inline void add(const int x, const int y)
{
ed[++tt]=y; nt[tt]=las[x]; las[x]=tt;
}
void DFS(const int x,const int FA)
{
in[x] = ++total;
bel[total] = x;
dep[x] = dep[FA] + 1;
maxdep = max(maxdep,dep[x]); if(V[dep[x]].size() == 0) V[dep[x]].push_back(-1);
V[dep[x]].push_back(in[x]); for(re i=las[x];i;i=nt[i]) DFS(ed[i], x);
ou[x] = total;
}
struct node{int a, b, id;}ask[N];
vector<int>TO[N];
bool cmp(const int &x, const int &y)
{
return ask[x].b < ask[y].b;
}
int a[N], c[N], lst[N], ans[N];
inline int lowbit(const int x) {return x&-x;}
inline int getsum(const int x)
{
int ret=0;
for(re i=x;i > 0;i-=lowbit(i)) ret += c[i];
return ret;
}
inline void modi(const int x,const int d)
{
for(re i=x;i<=n;i+=lowbit(i)) c[i] += d;
}
inline void solve(const int de) // 单独处理每一深度de
{
memset(lst, 0, sizeof(lst));
memset(c, 0 ,sizeof(c)); sort(TO[de].begin()+1, TO[de].end(), cmp);
int nn = V[de].size()-1, mm=TO[de].size()-1;
for(re i=1,k=1; i<=nn && k<=mm; ++i)
{
modi(i, 1); // 树状数组
int rea = bel[V[de][i]];
int color = a[rea];
if(lst[color] != 0) modi(lst[color], -1);
lst[color] = i; while(k<=mm && ask[TO[de][k]].b == i)
{
int tp = TO[de][k];
ans[ask[tp].id] = getsum(i) - getsum(ask[tp].a-1);
k++;
}
}
}
signed main()
{
ios::sync_with_stdio(false);
cin>>n;
int gf=2e5, m;
for(re i=1, getname=0;i<=n;++i)
{
string name; int father;
cin>>name>>father;
if(father != 0) add(father, i);
else add(gf, i);
if(!mp.count(name)) mp[name] = ++getname;
// 记录每种名字所代表的数字
a[i] = mp[name];
}
dep[0]=-1;
DFS(gf, 0); // 一个虚拟的根节点,使森林变成一棵树
cin>>m;
for(re i=1;i<=m;++i)
{
int x, y;
cin>>x>>y;
int dd = dep[x] + y;
if(dd <= maxdep && V[dd].size())
{
int l = lower_bound(V[dd].begin()+1, V[dd].end(), in[x])-V[dd].begin();
int r = upper_bound(V[dd].begin()+1, V[dd].end(), ou[x])-V[dd].begin()-1; // 记录在dd深度中,从l到r位
if(l <= r && 1 <= l && r < V[dd].size())
{
ask[i]=(node){l, r, i};
if(TO[dd].size() == 0) TO[dd].push_back(-1);
TO[dd].push_back(i);
}
}
}
for(re i=1;i<=n;++i) if(TO[i].size()) solve(i);
for(re i=1;i<=m;++i) cout<<ans[i]<<endl;
}

made by kzsn

热身训练1 Blood Cousins Return的更多相关文章

  1. [cf contest246] E - Blood Cousins Return

    [cf contest246] E - Blood Cousins Return time limit per test 3 seconds memory limit per test 256 meg ...

  2. Codeforces 246E - Blood Cousins Return (树上启发式合并)

    246E - Blood Cousins Return 题意 给出一棵家谱树,定义从 u 点向上走 k 步到达的节点为 u 的 k-ancestor,每个节点有名字,名字不唯一.多次查询,给出 u k ...

  3. Codeforces 246E Blood Cousins Return(树上启发式合并)

    题目链接 Blood Cousins Return #include <bits/stdc++.h> using namespace std; #define rep(i, a, b) f ...

  4. CF 246E. Blood Cousins Return [dsu on tree STL]

    题意: 一个森林,求k级后代中多少种不同的权值 用set维护每个深度出现的权值 一开始一直在想删除怎么办,后来发现因为当前全局维护的东西里都是当前子树里的,如果要删除那么当前一定是轻儿子,直接清空se ...

  5. codeforces246E Blood Cousins Return

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...

  6. CF 208E - Blood Cousins dfs序+倍增

    208E - Blood Cousins 题目:给出一棵树,问与节点v的第k个祖先相同的节点数有多少个. 分析: 寻找节点v的第k个祖先,这不就是qtree2简化版吗,但是怎么统计该祖先拥有多少个深度 ...

  7. Codeforces 208E - Blood Cousins(树上启发式合并)

    208E - Blood Cousins 题意 给出一棵家谱树,定义从 u 点向上走 k 步到达的节点为 u 的 k-ancestor.多次查询,给出 u k,问有多少个与 u 具有相同 k-ance ...

  8. CF208E Blood Cousins

    Blood Cousins 题目描述 小C喜欢研究族谱,这一天小C拿到了一整张族谱. 小C先要定义一下k-祖先. x的1-祖先指的是x的父亲 x的k-祖先指的是x的(k-1)-祖先的父亲 小C接下来要 ...

  9. CF 208E. Blood Cousins [dsu on tree 倍增]

    题意:给出一个森林,求和一个点有相同k级祖先的点有多少 倍增求父亲然后和上题一样还不用哈希了... #include <iostream> #include <cstdio> ...

随机推荐

  1. VUE005. 在data中使用 / 改变data,或在data中调用method函数

    使用三方UI库时经常会遇到在data中写入方法的场景,如Element-UI的级联选择器(动态加载part)需要在data中写入lazyLoad. 但后端总会给出意想不到的需求: 通过接口调取一串数据 ...

  2. Prism+WPF使用DependencyInjection实现AutoMapper的依赖注入功能

    前言 在使用PRISM+WPF开发项目的过程中,需要使用AutoMapper实现对象-对象的映射功能.无奈PRISM没有相关对AutoMapper相关的类库,于是转换一下思想,在nuget 中存在有关 ...

  3. 我用MRS-ClickHouse构建的用户画像系统,让老板拍手称赞

    摘要:在移动互联网时代,用户数量庞大,标签数量众多,用户标签的数据量巨大.用户画像系统中,对于标签的存储和查询,不同的企业有不同的实现方案.当前主流的实现方案采用ElasticSearch方案.但基于 ...

  4. 从线上日志统计接口访问量QPS

    这一阵子在面试,连续遇到好几家(大小厂都有)问我的项目线上qps的情况了,说实话,我作为一个大头兵,本来没关注过这个数据,只能含混地给个"大概.也许"的回答. 回来之后,我决定对业 ...

  5. Java Web实现登录验证码(Servlet+jsp)

    1.生成验证码图片(Servlet) import java.awt.Color; import java.awt.Font; import java.awt.Graphics2D; import j ...

  6. java中避免集合死链调用

    目录 1. 前言 2. 场景 3. 环境 3.1 开发环境准备 3.2 数据准备 3.2.1 Mysql数据库表及数据 3.2.2 redis库数据 4. 解决方式 5.完整代码 5.1Model 5 ...

  7. Linux系列(23) - echo

    作用:打印 格式:echo [选项] [输出内容] 选项:-e :支持反斜线控制的字符转换 前置条件:必须加选项-e才能使用 控制字符 作用 \a 输出警告音 \b 退格符,也就是向左删除键 \n 换 ...

  8. 怎么通俗的理解Netty呢?

    目录 Netty(3.X) 简单体验 Netty的事件驱动机制 Netty的源码阅读 Netty(3.X) 有了Netty,你可以实现自己的HTTP服务器,FTP服务器,UDP服务器,RPC服务器,W ...

  9. HTML 网页开发、CSS 基础语法——十二.CSS选择器

    选择器 基础选择器:标签选择器,id选择器,类选择器,通配符选择器 高级选择器:后代选择器,交集选择器,并集选择器 1. 标签选择器: • 优点:可以选中所有的同名标签,设置所有同名标签的公共样式. ...

  10. YbtOJ#526-折纸游戏【二分,hash】

    正题 题目链接:https://www.ybtoj.com.cn/problem/526 题目大意 一个\(n\times m\)的网格上有字母,你每次可以沿平行坐标轴对折网格,要求对折的对应位置字母 ...