Live2D

Solution -「ARC 101D」「AT4353」Robots and Exits

\(\mathcal{Description}\)

  Link.

  有 \(n\) 个小球,坐标为 \(x_{1..n}\);还有 \(m\) 个洞,坐标为 \(y_{1..m}\),保证上述坐标两两不同。每次操作可以将所有小球向左或向右平移一个单位,若有小球的坐标与洞重合则掉进洞内。求所有小球都进洞时有多少种不同的状态。答案对 \((10^9+7)\) 取模。

  \(n,m\le10^5\)

\(\mathcal{Solution}\)

  ARC 的题嘛……都这副德行。(

  不考虑仅有一个方向有洞的球,可见剩余球要不进入左边最近的洞,要不进入右边最近的洞。设一个距离左边洞 \(x\),右边洞 \(y\) 的小球为 \((x,y)\),那么问题被刻画为:

  平面上有若干点,每次将 \(x\) 轴向上或 \(y\) 轴向右平移一单位。每个点被染色为最先碰到它的坐标轴代表的颜色。求不同染色方案数。

  可证和原问题等价。DP 即可,注意处理转化后重合的坐标。

  复杂度 \(\mathcal O(n\log n)\)

\(\mathcal{Code}\)

/* Clearink */

#include <cstdio>
#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 )

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' );
}

const int MAXN = 1e5, MOD = 1e9 + 7;
int n, m, mx, x[MAXN + 5], y[MAXN + 5], dc[MAXN + 5];

inline int mul( const long long a, const int b ) { return a * b % MOD; }
inline int sub( int a, const int b ) { return ( a -= b ) < 0 ? a + MOD : a; }
inline void subeq( int& a, const int b ) { ( a -= b ) < 0 && ( a += MOD ); }
inline int add( int a, const int b ) { return ( a += b ) < MOD ? a : a - MOD; }
inline void addeq( int& a, const int b ) { ( a += b ) >= MOD && ( a -= MOD ); }

struct Point {
    int x, y;
    inline bool operator < ( const Point& p ) const {
        return x != p.x ? x < p.x : y > p.y;
    }
} pt[MAXN + 5];

struct BinaryIndexTree {
    int val[MAXN + 5];

    inline void upd( int x, const int v ) {
        for ( ; x <= mx; x += x & -x ) addeq( val[x], v );
    }

    inline int sum( int x ) {
        int ret = 0;
        for ( ; x; x -= x & -x ) addeq( ret, val[x] );
        return ret;
    }
} bit;

int main() {
    // freopen( "hole.in", "r", stdin );
    // freopen( "hole.out", "w", stdout );

    n = rint(), m = rint();
    rep ( i, 1, n ) x[i] = rint();
    rep ( i, 1, m ) y[i] = rint();

    int cnt = 0;
    rep ( i, 1, n ) {
        int p = std::lower_bound( y + 1, y + m + 1, x[i] ) - y;
        if ( p == 1 || p > m ) continue;
        pt[++cnt] = { x[i] - y[p - 1], y[p] - x[i] }, dc[cnt] = pt[cnt].y;
    }

    std::sort( pt + 1, pt + cnt + 1 );
    std::sort( dc + 1, dc + cnt + 1 );
    mx = std::unique( dc + 1, dc + cnt + 1 ) - dc;
    rep ( i, 1, cnt ) {
        pt[i].y = std::lower_bound( dc + 1, dc + mx, pt[i].y ) - dc + 1;
    }

    bit.upd( 1, 1 );
    rep ( i, 1, cnt ) {
        if ( pt[i].x == pt[i - 1].x && pt[i].y == pt[i - 1].y ) continue;
        int v = bit.sum( pt[i].y - 1 );
        bit.upd( pt[i].y, v );
    }
    wint( bit.sum( mx ) ), putchar( '\n' );
	return 0;
}


posted @ 2021-06-19 07:40  Rainybunny  阅读(37)  评论(0编辑  收藏  举报