虽然说好像这题有其他做法,但是在问题转化之后,使用CDQ分治是显而易见的

并且如果CDQ打的熟练的话,码量也不算大,打的也很快,思维难度也很小

没学过CDQ分治的话,可以去看看我的另一篇博客,是CDQ分治的入门教程

下面是正文:

首先整理一下条件:

每个点有三个属性,x,r,f

统计有多少对点i,j满足 min(ri,rj) >= |xi-xj| 且 |fi-fj| <= k,这样的点对被称作是“坏的”

对r值取min是个烦人的条件,于是我们把点按照r值从大到小排序,按照r值从大到小的顺序依次考虑每个点

这样对于每个点,我们只考虑它之前出现的点,也就是r值比他大的点,和他能不能组成“坏的”点对

这样的话,因为一个点i之前所有的点j的r值都比他大,所以 min(ri,rj) = ri

然后我们重新看一下问题:

按照指定的顺序依次加入点,每次加入一个点i,考虑它之前加入的所有点j,有多少个点满足 |xi-xj| <= ri 且 |fi-fj| <= k

再转化一下:

对于每个点i,考虑有多少个它之前的点j满足 xi-ri <= xj <= xi+ri 且 fi-k <= fj <= fi+k

我们把x和f这两个属性看做二维平面中的横纵坐标,问题就变成了:

向一个平面中添加一个点,查询指定矩形内点的个数

这是一个经典的三维偏序问题,可以用 线段树套线段树 或者 CDQ分治 来做

代码如下:

 #include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cassert>
#include <cctype>
#include <cmath>
#include <vector>
#include <queue>
#include <set>
#include <map> using namespace std;
typedef long long ll;
const int MAXN = ;
const int MAXF = ; int n, k; struct Item { // 每个点的信息
int r, x, f;
bool operator<( const Item &rhs ) const {
return r > rhs.r; // 按照r值排序
}
}item[MAXN]; inline int lowbit( int num ) { return num&(-num); }
namespace BIT { // 树状数组相关
int c[MAXF] = {};
void add( int x, int v ) {
for( ; x <= MAXF-; x += lowbit(x) )
c[x] += v;
}
int query( int x ) {
int sum = ;
for( ; x; x -= lowbit(x) )
sum += c[x];
return sum;
}
int query( int l, int r ) {
return query(r) - query(l-);
}
void clear( int x ) {
for( ; x <= MAXF-; x += lowbit(x) )
c[x] = ;
}
} struct Query {
int type, x, y, w;
// type == 1 表示查询 type == 0 表示修改
// w 表示查询对答案的贡献,为1或-1
bool operator<( const Query &rhs ) const {
if( x == rhs.x ) return type < rhs.type;
return x < rhs.x;
}
}query[MAXN*], tmp[MAXN*]; int qidx = ; ll ans = ; void cdq( int L, int R ) { // cdq分治主过程
if( R-L <= ) return;
int M = (L+R)>>; cdq(L,M); cdq(M,R);
int p = L, q = M, o = L;
while( p < M && q < R ) {
if( query[p] < query[q] ) {
if( query[p].type == ) BIT::add( query[p].y, );
tmp[o++] = query[p++];
} else {
if( query[q].type == ) ans += BIT::query( query[q].y ) * query[q].w;
tmp[o++] = query[q++];
}
}
while( p < M ) tmp[o++] = query[p++];
while( q < R ) {
if( query[q].type == ) ans += BIT::query( query[q].y ) * query[q].w;
tmp[o++] = query[q++];
}
for( int i = L; i < R; ++i ) {
if( query[i].type == ) BIT::clear( query[i].y );
query[i] = tmp[i];
}
} int main() {
scanf( "%d%d", &n, &k );
for( int i = ; i < n; ++i )
scanf( "%d%d%d", &item[i].x, &item[i].r, &item[i].f );
sort( item, item+n );
for( int i = ; i < n; ++i ) {
Item &it = item[i]; // 转化为平面上的添加和查询问题
int x1 = it.x-it.r, y1 = max( it.f-k, );
int x2 = it.x+it.r, y2 = it.f+k;
query[qidx++] = (Query){ , x1-, y1-, };
query[qidx++] = (Query){ , x1-, y2, - };
query[qidx++] = (Query){ , x2, y1-, - };
query[qidx++] = (Query){ , x2, y2, };
query[qidx++] = (Query){ , it.x, it.f, }; // 修改的w值没有意义
}
cdq(,qidx);
cout << ans << endl;
return ;
}

【题解】Radio stations Codeforces 762E CDQ分治的更多相关文章

  1. Radio stations CodeForces - 762E (cdq分治)

    大意: 给定$n$个三元组$(x,r,f)$, 求所有对$(i,j)$, 满足$i<j, |f_i-f_j|\le k, min(r_i,r_j)\ge |x_i-x_j|$ 按$r$降序排, ...

  2. Codeforces 669E cdq分治

    题意:你需要维护一个multiset,支持以下操作: 1:在某个时间点向multiset插入一个数. 2:在某个时间点在multiset中删除一个数. 3:在某个时间点查询multiset的某个数的个 ...

  3. Tufurama CodeForces - 961E (cdq分治)

    题面 One day Polycarp decided to rewatch his absolute favourite episode of well-known TV series " ...

  4. AI robots CodeForces - 1045G (cdq分治)

    大意: n个机器人, 位置$x_i$, 可以看到$[x_i-r_i,x_i+r_i]$, 智商$q_i$, 求智商差不超过$k$且能互相看到的机器人对数. 这个题挺好的, 关键是要求互相看到这个条件, ...

  5. BZOJ2244 [SDOI2011]拦截导弹 【cdq分治 + 树状数组】

    题目 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度.并且能够拦截任意速度的导弹,但是以后每一发炮弹都不能高于前一发的高度,其 ...

  6. CodeForces - 762E:Radio stations (CDQ分治||排序二分)

    In the lattice points of the coordinate line there are n radio stations, the i-th of which is descri ...

  7. codeforces 762E(cdq分治)

    题意: n个电台,每个电台有三个属性xi, ri, fi.分别代表电台的坐标,电台的播报范围,以及播报的频率. 对于一对电台i, j,若min(ri, rj) >= |xi - xj|,那么他们 ...

  8. Codeforces 1093E Intersection of Permutations [CDQ分治]

    洛谷 Codeforces 思路 一开始想到莫队+bitset,发现要T. 再想到分块+bitset,脑子一抽竟然直接开始写了,当然也T了. 最后发现这就是个裸的CDQ分治-- 发现\(a\)不变,可 ...

  9. Codeforces 1045G AI robots [CDQ分治]

    洛谷 Codeforces 简单的CDQ分治题. 由于对话要求互相看见,无法简单地用树套树切掉,考虑CDQ分治. 按视野从大到小排序,这样只要右边能看见左边就可以保证互相看见. 发现\(K\)固定,那 ...

随机推荐

  1. Ducci序列 (Ducci Sequence,ACM/ICPC Seoul 2009,UVa1594)

    题目描述: 题目思路: 直接模拟 #include<stdio.h> #include<string.h> #define maxn 105 int less(const ch ...

  2. 技本功丨知否知否,Redux源码竟如此意味深长(下集)

    上集回顾 Redux是如何使用的?首先再来回顾一下这个使用demo(谁让这段代码完整地展示了redux的使用) 如果有小伙伴对这段代码不是很理解的话,建议先去学习Redux的使用再来看这篇源码,这样更 ...

  3. 从零开始的Python学习Episode 5——字典

    字典 字典是另一种可变容器模型,且可存储任意类型对象. 一.添加 (1)直接添加 dict={'name':'smilepup'} dict['age']=20 dict['name']='piggy ...

  4. python—IDLE的shell上下翻看历史

    Alt+p和Alt+n,分别向上(history previous)和向下(history next)调出使用过的历史命令.

  5. C语言struct中的长度可变数组(Flexible array member)

    C_struct中的长度可变数组(Flexible array member) Flexible array member is a feature introduced in the C99 sta ...

  6. 【SSH进阶之路】Struts + Spring + Hibernate 进阶开端(一)

    [SSH进阶之路]Struts + Spring + Hibernate 进阶开端(一) 标签: hibernatespringstrutsssh开源框架 2014-08-29 07:56 9229人 ...

  7. 小程序的picker的range 是一个 Object Array (对象数组)

    小程序的picker的range 是一个 Object Array (对象数组) 数据: array: [{'id':1,'name':'Android'},{'id':2,'name':'IOS'} ...

  8. Thunder团队第二周 - Scrum会议3

    Scrum会议3 小组名称:Thunder 项目名称:爱阅app Scrum Master:代秋彤 工作照片: 参会成员: 王航:http://www.cnblogs.com/wangh013/ 李传 ...

  9. 第十七次ScrumMeeting会议

    第十七次Scrum Meeting 时间:2017/12/7 地点:线上+主235 人员:蔡帜 王子铭 游心 解小锐 王辰昱 李金奇 杨森 陈鑫 赵晓宇 照片: 目前工作进展 名字 今日 明天的工作 ...

  10. (一)Model的产生及处理

    MVC的概念其实最早可以追溯到很久很久以前,并不是WEB开发过程中所首创, 但是,MVC也适合WEB上的开发,并真正的在WEB开发领域广泛应用.MVC的第一个字母M是Model,承载着View层和Co ...