虽然说好像这题有其他做法,但是在问题转化之后,使用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. GET请求的写法-jmeter

    第一种写法:可以向post 请求一样写 第二种写法: /pinter/com/getSku?id=${__Random(1,100,rdmNum)}

  2. lr 常用操作

    lr脚本编写语法: web_add_cookie();:服务器注入cookies lr_save_string("网址或其他","参数2");:一个保存函数,它 ...

  3. Bitcoin: A Peer-to-Peer Electronic Cash System

    Bitcoin: A Peer-to-Peer Electronic Cash System Satoshi Nakamoto October 31, 2008 Abstract A purely p ...

  4. 基于Hadoop2.5.0的集群搭建

    http://download.csdn.net/download/yameing/8011891 一. 规划 1.  准备安装包 JDK:http://download.oracle.com/otn ...

  5. Special Offer! Super Price 999 Bourles!

    Description Polycarpus is an amateur businessman. Recently he was surprised to find out that the mar ...

  6. HBase 参考文档翻译之 Getting Started

    本篇是对HBase官方参考文档的大体翻译,介于本人英文水平实在有限,难免有纰漏之处.本篇不只是对官方文档的翻译,还加入了一些本人对HBase的理解.在翻译过程中,一些没有营养的废话,我就忽略了没有翻译 ...

  7. jsp文件中charset和pageEncoding的区别

    jsp文件中charset和pageEncoding的区别:  contentType的charset是指服务器发送给客户端时的内容编码,contentType里的charset=utf-8是指示页面 ...

  8. UVALive - 6856 Circle of digits 后缀数组+二分

    题目链接: http://acm.hust.edu.cn/vjudge/problem/82135 Circle of digits Time Limit: 3000MS 题意 把循环串分割成k块,让 ...

  9. 【week2】燃尽图

    燃尽图(burn down chart)是在项目完成之前,对需要完成的工作的一种可视化表示.燃尽图有一个Y轴(工作)和X轴(时间).理想情况下,该图表是一个向下的曲线,随着剩余工作的完成,“烧尽”至零 ...

  10. php缓存技术——memcache常用函数详解

    php缓存技术——memcache常用函数详解 2016-04-07 aileen PHP编程 Memcache函数库是在PECL(PHP Extension Community Library)中, ...