传送门

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. 原生JS 表单提交验证器

    转载:http://www.cnblogs.com/sicd/p/4613628.html 一.前言 最近在开发一个新项目,需要做登陆等一系列的表单提交页面.在经过“缜密”的讨论后,我们决定 不用外部 ...

  2. C#winfrom播放器动态加载歌词

    上周我们进行了结业项目答辩,是播放器项目.有一个关于播放器变唱歌边加载歌词的方法特别有意思,像酷狗那样子歌词和歌曲同步滚播的样子. 这里的工具是Visual Studio 2013,使用语言是C#和. ...

  3. AES —— JAVA中对称加密和解密

    package demo.security; import java.io.IOException; import java.io.UnsupportedEncodingException; impo ...

  4. Linux基础命令操作

    显示日期与时间:date date +%Y/%m/%d date +%H:%M 显示日历:cal 显示一整年(cal 2009) 显示一年中的某一个月 (cal [[month]] year) 例如 ...

  5. java反射 cglib asm相关资料

    有篇文章对java反射的调用的效率做了测试,写的比较好.猛击下面地址 http://www.blogjava.net/stone2083/archive/2010/09/15/332065.html ...

  6. 转《WF编程》笔记目录

    <WF编程>笔记目录 2008-03-18 09:33 by Windie Chai, 26803 阅读, 49 评论, 收藏, 编辑 WF笔记开始 <WF编程>系列之0 - ...

  7. WPF文章资源库

        MUHAMMAD SHUJAAT SIDDIQI

  8. C语言中结构体赋值问题的讨论

    今天帮师姐调一个程序的BUG,师姐的程序中有个结构体直接赋值的语句,在我印象中结构体好像是不能直接赋值的,正如数组不能直接赋值那样,我怀疑这个地方有问题,但最后证明并不是这个问题.那么就总结一下C语言 ...

  9. Eclipse SVN图标等设置

  10. 解决Ajax不能跨域的方法

    1.  Ajax不能跨域请求的原因 同源策略(Same Origin Policy),是一种约定,该约定阻止当前脚本获取或者操作另一个域下的内容.所有支持Javascript的浏览器都支持同源策略,也 ...