• 【题解】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分治 来做

    代码如下:

      1 #include <iostream>
      2 #include <cstring>
      3 #include <algorithm>
      4 #include <cstdio>
      5 #include <cstdlib>
      6 #include <cassert>
      7 #include <cctype>
      8 #include <cmath>
      9 #include <vector>
     10 #include <queue>
     11 #include <set>
     12 #include <map>
     13 
     14 using namespace std;
     15 typedef long long ll;
     16 const int MAXN = 100010;
     17 const int MAXF = 10020;
     18 
     19 int n, k;
     20 
     21 struct Item { // 每个点的信息
     22     int r, x, f;
     23     bool operator<( const Item &rhs ) const {
     24         return r > rhs.r; // 按照r值排序
     25     }
     26 }item[MAXN];
     27 
     28 inline int lowbit( int num ) { return num&(-num); }
     29 namespace BIT { // 树状数组相关
     30     int c[MAXF] = {0};
     31     void add( int x, int v ) {
     32         for( ; x <= MAXF-1; x += lowbit(x) )
     33             c[x] += v;
     34     }
     35     int query( int x ) {
     36         int sum = 0;
     37         for( ; x; x -= lowbit(x) )
     38             sum += c[x];
     39         return sum;
     40     }
     41     int query( int l, int r ) {
     42         return query(r) - query(l-1);
     43     }
     44     void clear( int x ) {
     45         for( ; x <= MAXF-1; x += lowbit(x) )
     46             c[x] = 0;
     47     }
     48 }
     49 
     50 struct Query {
     51     int type, x, y, w;
     52     // type == 1 表示查询 type == 0 表示修改
     53     // w 表示查询对答案的贡献,为1或-1
     54     bool operator<( const Query &rhs ) const {
     55         if( x == rhs.x ) return type < rhs.type;
     56         return x < rhs.x;
     57     }
     58 }query[MAXN*5], tmp[MAXN*5]; int qidx = 0;
     59 
     60 ll ans = 0;
     61 
     62 void cdq( int L, int R ) { // cdq分治主过程
     63     if( R-L <= 1 ) return;
     64     int M = (L+R)>>1; cdq(L,M); cdq(M,R);
     65     int p = L, q = M, o = L;
     66     while( p < M && q < R ) {
     67         if( query[p] < query[q] ) {
     68             if( query[p].type == 0 ) BIT::add( query[p].y, 1 );
     69             tmp[o++] = query[p++];
     70         } else {
     71             if( query[q].type == 1 ) ans += BIT::query( query[q].y ) * query[q].w;
     72             tmp[o++] = query[q++];
     73         }
     74     }
     75     while( p < M ) tmp[o++] = query[p++];
     76     while( q < R ) {
     77         if( query[q].type == 1 ) ans += BIT::query( query[q].y ) * query[q].w;
     78         tmp[o++] = query[q++];
     79     }
     80     for( int i = L; i < R; ++i ) {
     81         if( query[i].type == 0 ) BIT::clear( query[i].y );
     82         query[i] = tmp[i];
     83     }
     84 }
     85 
     86 int main() {
     87     scanf( "%d%d", &n, &k );
     88     for( int i = 0; i < n; ++i )
     89         scanf( "%d%d%d", &item[i].x, &item[i].r, &item[i].f );
     90     sort( item, item+n );
     91     for( int i = 0; i < n; ++i ) {
     92         Item &it = item[i]; // 转化为平面上的添加和查询问题
     93         int x1 = it.x-it.r, y1 = max( it.f-k, 1 );
     94         int x2 = it.x+it.r, y2 = it.f+k;
     95         query[qidx++] = (Query){ 1, x1-1, y1-1, 1 };
     96         query[qidx++] = (Query){ 1, x1-1, y2, -1 };
     97         query[qidx++] = (Query){ 1, x2, y1-1, -1 };
     98         query[qidx++] = (Query){ 1, x2, y2, 1 };
     99         query[qidx++] = (Query){ 0, it.x, it.f, 0 }; // 修改的w值没有意义
    100     }
    101     cdq(0,qidx);
    102     cout << ans << endl;
    103     return 0;
    104 }
  • 相关阅读:
    Oracle Instant Client(即时客户端) 安装与配置
    面试中经典的数据库问题
    MySQL 大表优化方案
    mysql中Timestamp,Time,Datetime 区别
    HTML学习之给div高度设置百分比不生效的问题
    textarea文本域宽度和高度width及height自动适应实现代码
    JAVA基础----java中E,T,?的区别?
    去除ArrayList集合中的重复自定义对象元素
    sql select中加入常量列
    mysql 将null转代为0
  • 原文地址:https://www.cnblogs.com/mlystdcall/p/6351344.html
Copyright © 2020-2023  润新知