【题解】Radio stations Codeforces 762E CDQ分治
虽然说好像这题有其他做法,但是在问题转化之后,使用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分治的更多相关文章
- 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$降序排, ...
- Codeforces 669E cdq分治
题意:你需要维护一个multiset,支持以下操作: 1:在某个时间点向multiset插入一个数. 2:在某个时间点在multiset中删除一个数. 3:在某个时间点查询multiset的某个数的个 ...
- Tufurama CodeForces - 961E (cdq分治)
题面 One day Polycarp decided to rewatch his absolute favourite episode of well-known TV series " ...
- AI robots CodeForces - 1045G (cdq分治)
大意: n个机器人, 位置$x_i$, 可以看到$[x_i-r_i,x_i+r_i]$, 智商$q_i$, 求智商差不超过$k$且能互相看到的机器人对数. 这个题挺好的, 关键是要求互相看到这个条件, ...
- BZOJ2244 [SDOI2011]拦截导弹 【cdq分治 + 树状数组】
题目 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度.并且能够拦截任意速度的导弹,但是以后每一发炮弹都不能高于前一发的高度,其 ...
- 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 ...
- codeforces 762E(cdq分治)
题意: n个电台,每个电台有三个属性xi, ri, fi.分别代表电台的坐标,电台的播报范围,以及播报的频率. 对于一对电台i, j,若min(ri, rj) >= |xi - xj|,那么他们 ...
- Codeforces 1093E Intersection of Permutations [CDQ分治]
洛谷 Codeforces 思路 一开始想到莫队+bitset,发现要T. 再想到分块+bitset,脑子一抽竟然直接开始写了,当然也T了. 最后发现这就是个裸的CDQ分治-- 发现\(a\)不变,可 ...
- Codeforces 1045G AI robots [CDQ分治]
洛谷 Codeforces 简单的CDQ分治题. 由于对话要求互相看见,无法简单地用树套树切掉,考虑CDQ分治. 按视野从大到小排序,这样只要右边能看见左边就可以保证互相看见. 发现\(K\)固定,那 ...
随机推荐
- [Clr via C#读书笔记]Cp12泛型
Cp12泛型 Generic: 特点 源代码保护 类型安全 清晰代码 更佳性能 Framework中的泛型 System.Collections.Generic; 开放类型,封闭类型:每个封闭类型都有 ...
- 将SqlDataReader 数据集转化为datatbale ,在将datatable 转化为iList
public IList GetModelList(string tablename, string where) { IList list = null; DataTable dataTable = ...
- Entity Framework 基本概念
概念 LINQ to Entities 一种 LINQ 技术,使开发人员可以使用 LINQ 表达式和 LINQ 标准查询运算符,针对实体数据模型 (EDM) 对象上下文创建灵活的强类型化查询. ESQ ...
- 从oracle导入hive
sqoop import --connect jdbc:oracle:thin:@10.39.1.43:1521/rcrm --username bi_query --password ####### ...
- BZOJ 3790 神奇项链 hash/后缀自动机+贪心
Description 母亲节就要到了,小 H 准备送给她一个特殊的项链.这个项链可以看作一个用小写字母组成的字符串,每个小写字母表示一种颜色. 为了制作这个项链,小 H 购买了两个机器.第一个机器可 ...
- ACM 第十三天
训练赛题目 题目地址:https://odzkskevi.qnssl.com/415c275cb0a15fcb4ede21b8cb5297de?v=1533963116 A题代码: #includ ...
- Oracle查询字段中有空格的数据
一.问题说明 最近在给某个用户下的表批量添加注释时,在程序中将注释名用trim()过滤一遍就可以了,但是在程序执行成功后怎么检测添加的注释名是否有空格存在呢? 二.解决方法 1.SELECT * FR ...
- React 16.x & Hooks
React 16.x & Hooks Hooks https://reactjs.org/docs/hooks-intro.html https://reactjs.org/docs/hook ...
- 在html在添加cookie和读取cookie
1.保存cookie var oDate = new Date(); oDate.setDate(oDate.getDate() + );//有效期为30天 document.cookie = &qu ...
- VS2012完全卸载
1.先交VS2012的ISO通过Ultraiso载入2.DOS命中输入 I:\vs_ultimate.exe /uninstall /force 或 I:vs_ultimate.exe /uninst ...