• Solution -「JOISC 2021」「LOJ #3491」道路建设


    (mathcal{Description})

      Link.

      平面上有 (n) 个互不重合的点 ((x_{1..n},y_{1..n})),求其两两曼哈顿距离的前 (m) 小值。

      (n,mle2.5 imes10^5)

    (mathcal{Solution})

      会做,但不完全会做。

      数前 (k) 小的一种技术是:将解大致分类,在每类中维护最优解,一起放入堆中迭代。

      应用到本题,按 ((x,y)) 的二维偏序排序后,对于每个点,尝试维护其前方的所有点与它构成的答案信息。具体地,对于当前 ((x,y)),维护了 ((x',y')) 与它的曼哈顿距离,必然有 (x'le x),所以仅需考虑 (y)(y') 的关系,分别取正负号,用可持久化线段树维护一发即可。

      复杂度 (mathcal O((n+m)log n)),空间同阶。

    (mathcal{Code})

    /* Clearink */
    
    #include <queue>
    #include <cstdio>
    #include <vector>
    #include <cassert>
    #include <iostream>
    #include <algorithm>
    
    #define rep( i, l, r ) for ( int i = l, rep##i = r; i <= rep##i; ++i )
    #define per( i, r, l ) for ( int i = r, per##i = l; i >= per##i; --i )
    
    typedef long long LL;
    #define int LL
    typedef std::pair<int, int> PII;
    typedef std::pair<LL, int> PLI;
    #define fi first
    #define se second
    
    inline int rint() {
        int x = 0, f = 1, s = getchar();
        for ( ; s < '0' || '9' < s; s = getchar() ) f = s == '-' ? -f : f;
        for ( ; '0' <= s && s <= '9'; s = getchar() ) x = x * 10 + ( s ^ '0' );
        return x * f;
    }
    
    template<typename Tp>
    inline void wint( Tp x ) {
        if ( x < 0 ) putchar( '-' ), x = -x;
        if ( 9 < x ) wint( x / 10 );
        putchar( x % 10 ^ '0' );
    }
    
    inline int iabs( const int a ) { return a < 0 ? -a : a; }
    
    const int MAXN = 2.5e5;
    const LL IINF = 1ll << 60;
    int n, m, mx, dy[MAXN + 5], root[MAXN + 5];
    PII pt[MAXN + 5];
    std::vector<int> ybuc[MAXN + 5];
    std::priority_queue<PLI, std::vector<PLI>, std::greater<PLI> > heap;
    
    struct SegmentTree {
        static const int MAXND = 1e7;
        int node, ch[MAXND][2];
        PII amn[MAXND], smn[MAXND];
    
        SegmentTree() { amn[0] = smn[0] = { IINF, 0 }; }
    
        inline void copy( const int u, const int v ) {
            ch[u][0] = ch[v][0], ch[u][1] = ch[v][1],
            amn[u] = amn[v], smn[u] = smn[v];
        }
    
        inline void pushup( const int u ) {
            amn[u] = std::min( amn[ch[u][0]], amn[ch[u][1]] );
            smn[u] = std::min( smn[ch[u][0]], smn[ch[u][1]] );
        }
    
        inline void modify( int& u, const int l, const int r,
          const int x, const int y ) {
            int v = u, mid = l + r >> 1; copy( u = ++node, v );
            if ( l == r ) {
                if ( x == IINF ) u = 0;
                else amn[u] = { -x + dy[y], l }, smn[u] = { -x - dy[y], l };
                return ;
            }
            if ( y <= mid ) modify( ch[u][0], l, mid, x, y );
            else modify( ch[u][1], mid + 1, r, x, y );
            pushup( u );
        }
    
        inline PII query( const int u, const int l, const int r,
          const int ql, const int qr, const bool type ) const {
            if ( !u ) return { IINF, 0 };
            if ( ql <= l && r <= qr ) return type ? amn[u] : smn[u];
            int mid = l + r >> 1; PII ret( IINF, 0 );
            if ( ql <= mid ) {
                ret = std::min( ret, query( ch[u][0], l, mid, ql, qr, type ) );
            }
            if ( mid < qr ) {
                ret = std::min( ret, query( ch[u][1], mid + 1, r, ql, qr, type ) );
            }
            return ret;
        }
    
        inline PLI calc( const int rt, const int x, const int y ) {
            PII up( query( rt, 1, mx, y, mx, true ) ),
              dn( query( rt, 1, mx, 1, y, false ) );
            LL u = 0ll + x - dy[y] + up.fi, d = 0ll + x + dy[y] + dn.fi;
            if ( u <= d ) return PLI( u, up.se );
            else return PLI( d, dn.se );
        }
    } sgt;
    
    signed main() {
        n = rint(), m = rint();
        rep ( i, 1, n ) pt[i].fi = rint(), dy[i] = pt[i].se = rint();
        
        std::sort( pt + 1, pt + n + 1 );
        std::sort( dy + 1, dy + n + 1 );
        mx = std::unique( dy + 1, dy + n + 1 ) - dy - 1;
        rep ( i, 1, n ) {
            pt[i].se = std::lower_bound( dy + 1, dy + mx + 1, pt[i].se ) - dy;
            ybuc[pt[i].se].push_back( pt[i].fi );
        }
    
        rep ( i, 1, mx ) std::sort( ybuc[i].begin(), ybuc[i].end() );
    
        rep ( i, 2, n ) {
            root[i] = root[i - 1];
            sgt.modify( root[i], 1, mx, pt[i - 1].fi, pt[i - 1].se );
            heap.push( { sgt.calc( root[i], pt[i].fi, pt[i].se ).fi, i } );
        }
    
        while ( m-- ) {
            PLI p( heap.top() ); heap.pop();
            wint( p.fi ), putchar( '
    ' );
    
            int yv( sgt.calc( root[p.se], pt[p.se].fi, pt[p.se].se ).se );
            int x = 0ll + iabs( dy[pt[p.se].se] - dy[yv] ) + pt[p.se].fi - p.fi;
            int id = std::lower_bound( ybuc[yv].begin(), ybuc[yv].end(), x )
              - ybuc[yv].begin(), nx = id ? ybuc[yv][id - 1] : IINF;
    
            sgt.modify( root[p.se], 1, mx, nx, yv );
            heap.push( { sgt.calc( root[p.se], pt[p.se].fi, pt[p.se].se ).fi,
              p.se } );
        }
        return 0;
    }
    
    
  • 相关阅读:
    第五章 调优案例分析与实战
    第六章 类文件结构
    推送和即时通迅早写完了,,一直没更新,,期末考了。
    Node.js安装备忘录
    将MyEclipse项目导入到Eclipse中
    40个Java集合类面试题和答案(转载)
    可适配平板、手机的Web开发方式
    一次Web请求过程详解
    常见HTTP状态码
    Web前端视频播放及视频的云存储
  • 原文地址:https://www.cnblogs.com/rainybunny/p/14915187.html
Copyright © 2020-2023  润新知