AGC 009 C

link

题意:\(n\) 个不同的数,分成两个集合 \(A,B\)\(A\) 中任意元素差不小于 \(x\)\(B\) 中任意元素差不小于 \(y\),求方案数。

线性 dp,有一丢丢莫名神似 CSP,,

记录一个题解的神仙做法:

不妨假设 \(x<y\)

首先根据抽屉原理,连续三个数必有两个在同一集合,所以若 \(a_{i+2}-a_i \lt x\) 显然无解。

\(f_i\) 表示 \(i\) 结尾且 \(i\)\(B\) 集合的方案数。

有转移:\(f_i = \sum_{a_i-a_j\ge y\land (j,i)\in A} f_j\)

合法的转移是一段后缀,随便转移。

可以用指针记录当前 \(j\) 合法的第一个位置,记录后缀和,直接把后缀和贡献到当前的 \(i\) 上,复杂度 \(O(n)\)

考虑如何判合法:如果当前的 \(i\) 不满足 \(a_i-a_{i-1}\ge x\),说明 \(i\)\(i-1\) 已经不能同时放 \(A\) 了。这时后缀和就要清零了,指针也随之挪到 \(i-1\)

那为什么其他情况保证合法呢?注意到我们开始时有保证 \(a_{i+2}-a_i\ge x\)!所以答案非零时这样做是对的。这也正是如此设计状态的原因!!

实现时有一个技巧是在序列首尾添加极小值和极大值,这样答案就是 \(f_{n+1}\)

代码短小精悍!

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
typedef double db;
typedef unsigned long long ull;
typedef long double ldb;
typedef pair<int, int> pii;

#define pb push_back
#define pc putchar
#define sp pc(' ')
#define et pc('\n')
#define debug cerr<<"--ERROR--\n"
#define rep(i, a, b) for(int i = (a); i <= (b); ++i)
#define per(i, a, b) for(int i = (a); i >= (b); --i)
#define mem(a, x) memset(a, x, sizeof(a))
#define in(a, n) rep(i, 1, n) a[i]=rd()
#define all(x) x.begin(), x.end()

inline ll rd(){ll x=0; int f=1; char c=getchar(); while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-48; c=getchar();} return x*f;}
inline void wr(ll x){if(x<0) putchar('-'), x=-x; static int stk[35]; int tp=0; do stk[tp++]=x%10;while(x/=10); do pc(stk[--tp]^48);while(tp);}

//const ldb eps = 1e-9;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int mo = 1e9+7;
const int N = 1e5+3;

int n, f[N];
ll a[N], x, y;

void clear() {  }
void add(int &a, int b) {
	if((a += b) >= mo) a -= mo;
}
signed main() {
//  freopen(".in", "r", stdin);
//  freopen(".out", "w", stdout);

int TT = 1;
//TT = rd();
while(TT--)
{
	clear();
	cin >> n >> x >> y;
	in(a, n);
	if(x > y) swap(x, y);
	a[++n] = INF, a[0] = -INF;
	rep(i, 1, n-1) if(a[i+1] - a[i-1] < x) return debug, wr(0), 0;
	int j=0, s=0;
	f[0] = 1;
	rep(i, 1, n) {
		while(a[i]-a[j] >= y) add(s, f[j]), ++j;
		f[i] = s;
		if(a[i]-a[i-1] < x) s=0, j=i-1;
	}
	wr(f[n]);
    et;
}
    return 0;
}

posted @ 2024-11-25 21:20  lowbit  阅读(24)  评论(0)    收藏  举报