[ARC101F] Robots and Exits

本文思路基本来自于这篇题解
在一个数轴上有 \(n\)robot\(m\)exit

每次操作可以把所有 robot 同时向左或向右,所有 robot 都到过 exit 之后停止操作。

robotexit 溜走的方案数,两个方案不同当且仅当有一个 robot 从不同的 exit 离开。

现在我们将对一个 robot 进行研究。我们发现只有改变他 向左或向右的最大值 的移动才会对这个 robot 有效果。 然后将 robot 的路线放在二维坐标图上初值为 \((0,0)\) 横纵坐标,第 \(i\)robot 距离它最近的两边 exit 的距离分别是 \(a_i\) \(b_i\),那么答案就取决于先碰到 \(x=a_i\) 还是 \(y=b_i\)

robot 的坐标转换为 \((a_i-0.5,b_i-0.5)\)。那象对于所有 robot 的移动路线,如果 robot 的坐标在其下面那么将会在 左侧出口离开 如果在右面则会从右侧出口离开。

感性理解一下,这样的直线数就等价于卡在每个 robot 左边左上角的直线数,那转移方程显然

\[f_i=\Sigma_{a_j<a_i,b_j<b_i}f_j+1 \]

套路问题

#include<bits/stdc++.h>
#define RG register
#define LL long long
#define U(x, y, z) for(RG int x = y; x <= z; ++x)
#define D(x, y, z) for(RG int x = y; x >= z; --x)
#define update(x, y) (x = x + y >= mod ? x + y - mod : x + y)
using namespace std;
void read(){}
template<typename _Tp, typename... _Tps>
void read(_Tp &x, _Tps &...Ar) {
	x = 0; char ch = getchar(); bool flg = 0;
	for (; !isdigit(ch); ch = getchar()) flg |= (ch == '-');
	for (; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + (ch ^ 48);
	if (flg) x = -x;
	read(Ar...);	
}
inline char Getchar(){ char ch; for (ch = getchar(); !isalpha(ch); ch = getchar()); return ch;}
template <typename T> inline void write(T n){ char ch[60]; bool f = 1; int cnt = 0; if (n < 0) f = 0, n = -n; do{ch[++cnt] = char(n % 10 + 48); n /= 10; }while(n); if (f == 0) putchar('-'); for (; cnt; cnt--) putchar(ch[cnt]);}
template <typename T> inline void writeln(T n){write(n); putchar('\n');}
template <typename T> inline void writesp(T n){write(n); putchar(' ');}
template <typename T> inline void chkmin(T &x, T y){x = x < y ? x : y;}
template <typename T> inline void chkmax(T &x, T y){x = x > y ? x : y;}
template <typename T> inline T Min(T x, T y){return x < y ? x : y;}
template <typename T> inline T Max(T x, T y){return x > y ? x : y;}
inline void readstr(string &s) { s = ""; static char c = getchar(); while (isspace(c)) c = getchar(); while (!isspace(c)) s = s + c, c = getchar();}
inline void FO(string s){freopen((s + ".in").c_str(), "r", stdin); freopen((s + ".out").c_str(), "w", stdout);}

const int N = 1e5 + 10, mod = 1e9 + 7;
int n, m, a[N], b[N], cnt, un[N];
#define pii pair<int, int>
#define fi first
#define se second
pii node[N];
struct BIT {
	int c[N];
	#define lb(x) (x & -x)
	inline void modify(int x, int p) {
		for (; x <= cnt; x += lb(x))
			update(c[x], p);
	}

	inline int query(int x) {
		int res = 0;
		for (; x; x -= lb(x))
			update(res, c[x]);
		return res;
	}
} tr;

int main(){
	//FO("");
	read(n, m);
	U(i, 1, n) read(a[i]);
	U(i, 1, m) read(b[i]);

	int tot = 0;
	U(i, 1, n) {
		int pos = lower_bound(b + 1, b + m + 1, a[i]) - b;
		if (pos == 1 || pos > m) continue ;
		node[++tot] = {a[i] - b[pos - 1], - (b[pos] - a[i])};
		un[tot] = -node[tot].se;
	}

	sort(node + 1, node + tot + 1);
	U(i, 1, n) node[i].se = -node[i].se;
	sort(un + 1, un + tot + 1);
	cnt = unique(un + 1, un + tot + 1) - un;
	U(i, 1, tot) node[i].se = lower_bound(un + 1, un + cnt, node[i].se) - un + 1;

	tr.modify(1, 1);
	U(i, 1, tot) {
		if (node[i].fi == node[i - 1].fi && node[i].se == node[i - 1].se) continue;
        int t = tr.query(node[i].se - 1);
        tr.modify(node[i].se, t);
	}

	writeln(tr.query(cnt));
	return 0;
}
posted @ 2022-11-03 15:12  Southern_Way  阅读(29)  评论(0)    收藏  举报