虽然说好像这题有其他做法,但是在问题转化之后,使用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. ionic typescript--验证码发送倒计时功能

    1.新建页面 ionic g page forget   2.mode.html文件 <ion-item> <ion-input clearInput [(ngModel)]='co ...

  2. POJ 3028 Shoot-out(概率DP)

    Description This is back in the Wild West where everybody is fighting everybody. In particular, ther ...

  3. 【转】再谈PHP、Python与Ruby

    原文链接:http://www.nowamagic.net/librarys/veda/detail/2504 一句话总结 简单地总结: 假如你想帮他尽快找个活儿,赚到钱,推荐PHP. 假如你想让他成 ...

  4. 路由器如何设置上网(TP-LINK)

    最近宿舍公用的网络一直不太稳定,正赶上毕业季,本来就打算自己买一台自用的路由器,于是我从一个毕业的师姐手里15RMB收了一台路由器,师姐还给了我一根5m的网线和两根全新15m的,感觉光网线就赚翻了. ...

  5. Java学习个人备忘录之异常

    概述 异常:是在运行时期发生的不正常情况. 在java中用类的形式对不正常情况进行了描述和封装对象. 描述不正常的情况的类,就称为异常类. 以前正常流程代码和问题处理代码相结合,现在将正常流程代码和问 ...

  6. 1001 Duplicate Pair

    1.题目戳这里 2.代码: #include<stdio.h> #include<string.h> int main() { int n; while(scanf(" ...

  7. 后端设置cookie写不到前端页面

    javax.servlet.http.Cookie cookie = new javax.servlet.http.Cookie("id",session.getId()); co ...

  8. Personal summary 个人总结

    一.请回望开学时的第一次作业,你对于软件工程课程的想象 对比开篇博客你对课程目标和期待,"希望通过实践锻炼,增强计算机专业的能力和就业竞争力",对比目前的所学所练所得,在哪些方面达 ...

  9. COM 自动化控制Excel应用程序

    class Program { static void Main(string[] args) { var dt = new System.Data.DataTable(); dt.Columns.A ...

  10. H3C SNMP配置解析

    华为交换机snmp配置 snmp-agent                                           /使能snmp服务/snmp-agent local-engineid ...