Live2D

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

Description

  Link.

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

  n,m105

Solution

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

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

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

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

  复杂度 O(nlogn)

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 @   Rainybunny  阅读(39)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
历史上的今天:
2020-06-19 Solution -「CF 623E」Transforming Sequence
点击右上角即可分享
微信分享提示