传送门

Problem Statement

You are given a tree where each node is labeled from 1 to n. How many similar pairs(S) are there in this tree?

A pair (A,B) is a similar pair if the following are true:

  • node A is the ancestor of node B
  • abs(A−B)≤T

Input format: 
The first line of the input contains two integers, n and T. This is followed by n−1 lines, each containing two integers si and ei where node si is a parent to node ei.

Output format: 
Output a single integer which denotes the number of similar pairs in the tree.

Constraints: 
1≤n≤100000 
0≤T≤n 
1≤si, ei ≤n

Sample Input:

5 2
3 2
3 1
1 4
1 5

Sample Output:

4

Explanation: 
The similar pairs are: (3, 2) (3, 1) (3, 4) (3, 5).

You can have a look at the tree image here

-------------------------------------------------------------
Solution:
题目给出一棵有根树,要求统计其中满足以下条件的点对(A, B)的数目
(1) A是B的祖先(但A不能等于B,即A应是B的合法(proper)祖先)
(2)abs(A-B)<=T(即两点编号之差的绝对值应不大于T)
--------------------------------------------------------
解法不难想,类似于树形DP,DFS遍历这棵有根树,以后序(或者说后序遍历)将各个顶点的编号逐一放到集合中。在进入以顶点u为根的子树时,先查询当前集合中有多少节点v满足 abs(v-u)<=T,遍历完这棵子树后在查询一次,由于新添进集合的都是u的后代,所以两次结果相减便是符合条件的点对(u,x)的数目。对每个节点都做类似的查询结果加起来就是答案。
--------------------------------------------------------------
至此,问题归结为如何维护这个集合,显然树状数组(BIT)是最合适的
#include <bits/stdc++.h>
using namespace std;
int T, n;
const int N(1e5+);
int bit[N];
int sum(int x){
int s=;
while(x){
s+=bit[x];
x-=x&-x;
}
return s; //error-prone
}
void add(int x){
while(x<=n){
bit[x]++;
x+=x&-x;
}
}
int get_ans(int x){
int l=max(x-T-, );
int r=min(n, x+T);
return sum(r)-sum(l);
}
int par[N];
vector<int> g[N];
long long ans;
void dfs(int u){
int tmp=get_ans(u);
for(int i=; i<g[u].size(); i++){
int &v=g[u][i];
dfs(v);
}
ans+=get_ans(u)-tmp;
add(u);
}
int main(){
//freopen("in", "r", stdin);
cin>>n>>T;
for(int i=, u, v; i<n; i++){
cin>>u>>v;
par[v]=u;
g[u].push_back(v);
}
int root=;
while(par[root])
root=par[root];
dfs(root);
cout<<ans<<endl;
}

--------------------------------------------

我们在考虑能否用C++ STL中的 set实现这个集合

显然我们需要支持3种操作

1. 插入,set OK

2.查询集合中大于x的数有多少个

3.查询集合中小于x的数有多少个

下面的资料摘自C++ Primer (5th. edition)

P. 330

Table 9.2 Contianer Operations

Type Aliases

difference_type Signed integral type big enough to hold the distance between two iterators

------------------------------------------------------------------------------------------------------------
我们知道set和map都支持upper_bound(),lower_bound(),可尝试用这两个函数来实现上述后两个查询。
比如我们想查询集合s中在[L, R]范围内的数有多少个,试着写成
set<int> s;
int f(int l, int r){
return s.upper_bound(r)-s.lower_bound(l);
}

但这是行不通的,编译时报错:

:no match for ‘operator-’ (operand types are ‘std::set<int>: :iterator {aka std::_Rb_tree_const_iterator<int>}’ and ‘std::set<int>::iterator {aka std::_Rb_tree_const_iterator<int>}’)

因为set<int>::iterator不支持-(减法)

------------------------------------------------

只能写成

set<int> s;
int f(int l, int r){
auto b=s.lower_bound(l), e=s.upper_bound(r);
int res=;
while(b!=e){ //use != rather than <
++b;
++res;
}
return res;
}

但这样写复杂度是O(n),不能承受。

Bjarne Stroustrup TC++PL (4th. edition) P.954

The reason to use != rather than < for testing whether we have reached the end is partially because that is

the more precise statement of what we testing for and partially because only random-access iterators support <.

----------------------------------------------------------

 
 
 

hackerrank Similar Pair的更多相关文章

  1. R语言-混合型数据聚类

    利用聚类分析,我们可以很容易地看清数据集中样本的分布情况.以往介绍聚类分析的文章中通常只介绍如何处理连续型变量,这些文字并没有过多地介绍如何处理混合型数据(如同时包含连续型变量.名义型变量和顺序型变量 ...

  2. 【LeetCode】734. Sentence Similarity 解题报告(C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 只修改区间起终点 日期 题目地址:https://le ...

  3. RFID Exploration and Spoofer a bipolar transistor, a pair of FETs, and a rectifying full-bridge followed by a loading FET

    RFID Exploration Louis Yi, Mary Ruthven, Kevin O'Toole, & Jay Patterson What did you do? We made ...

  4. *[hackerrank]Algorithmic Crush

    https://www.hackerrank.com/contests/w4/challenges/crush 第一眼觉得要用线段树,但据说会超时.其实这个可以通过生成pair排序来做. #inclu ...

  5. 【HackerRank】How Many Substrings?

    https://www.hackerrank.com/challenges/how-many-substrings/problem 题解 似乎是被毒瘤澜澜放弃做T3的一道题(因为ASDFZ有很多人做过 ...

  6. [Functional Programming] mapReduce over Async operations and fanout results in Pair(rejected, resolved) (fanout, flip, mapReduce)

    This post is similar to previous post. The difference is in this post, we are going to see how to ha ...

  7. Code Signal_练习题_Are Similar?

    Two arrays are called similar if one can be obtained from another by swapping at most one pair of el ...

  8. MOSFET pair makes simple SPDT switch

    With an n- and p-channel MOSFET, you can easily implement a single-pole double-throw (SPDT) switch t ...

  9. 2017-5-14 湘潭市赛 Similar Subsequence 分析+四维dp+一些简单优化

    Similar Subsequence Accepted : Submit : Time Limit : MS Memory Limit : KB Similar Subsequence For gi ...

随机推荐

  1. IRIS数据集的分析-数据挖掘和python入门-零门槛

    所有内容都在python源码和注释里,可运行! ########################### #说明: # 撰写本文的原因是,笔者在研究博文“http://python.jobbole.co ...

  2. 使用Filter跟踪Asp.net MVC页面加载时间

    最近,客户一直反馈系统使用慢,有时候能够指出具体是哪个页面,有时候又只是笼统地反馈慢.这种问题就像是幽灵一样,非常不好处理.因为导致这种问题的因素非常之多,而且在开发工程中,很难模拟出实际运行是的环境 ...

  3. React 性能优化总结

    初学者对React可能满怀期待,觉得React可能完爆其它一切框架,甚至不切实际地认为React可能连原生的渲染都能完爆--对框架的狂热确实会出现这样的不切实际的期待.让我们来看看React的官方是怎 ...

  4. MongoDB学习笔记~大叔分享批量添加—批量更新—批量删除

    回到目录 说它是批量操作,就是说将集合对象一次提交到服务器,并对数据进行持久化,如果您的代码是一次一次的提交,那不算是批量操作!在之前的mongodb仓储中并没有对批量更新和批量删除进行实现,而今天在 ...

  5. SCCM 2012 R2安装部署过程和问题(三)

    上篇 SCCM 2012 R2安装部署过程和问题(二) 个人认为对于使用SCCM 2012的最重要的经验是耐心. SCCM采用分布式部署的架构,不同的站点角色可以部署在不同的服务器上,站点角色之间的通 ...

  6. jq attr()改变checkbox的checked无效!!!!

    今天做项目发现用attr()改变checked,实现全选功能的时候发现,第一次点击有效,之后点击全选功能便实效. 一开始以为是自己写错了,在各种碰壁之后,才猛然发现,原来这是jq的一个小bug. 在j ...

  7. 追MM的各种算法

    原文:http://blog.sae.sina.com.cn/archives/3542#more-3542 看到一篇文章把算法描述的相当的好,先收藏了! 动态规划 基本上就是说:你追一个MM的时候, ...

  8. 【小白的CFD之旅】05 补充基础

    黄师姐是一个很干脆果敢的人,从她的日常装扮就能显露出来.卡帕运动装,白色运动鞋,马尾辫,这是小白对黄师姐的第一印象.“明天早上九点钟来实验室,我给你安排这阵子的任务.”黄师姐对小白说.说话语气和老蓝一 ...

  9. 【小白的CFD之旅】02 江小白

    虽然已经是9月份了,但是西南地区的湿热天气依然将小白热成了狗.独自一个人来到这号称天府之国的西南城市,小白却一点都没感受到这天府之国的友好.毒辣的阳光像利剑一样照射到身上,让人感觉如在蒸笼中一样.从炎 ...

  10. 去除多余的cell 和最后一行cell显示顶头底线

    去除多余cell YourTableview.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero]; 最后一行cell底线顶头显示 s ...