AGC 009 C
题意:\(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;
}

浙公网安备 33010602011771号