# [容斥][单调栈优化dp] Codeforces 1591F Non-equal Neighbours

## 题解

$$f[i]$$ 表示满足条件的 $$\{b_n\}$$ 的长为 $$i$$ 的前缀的方案数，我们可以枚举前 $$i$$ 个数的一个后缀，使这个后缀里的所有数相等。则有

$f[i]=\sum_{j=0}^{i-1} (-1)^{i-j-1}\times f[j]\times \min_{k=j+1}^i \{ a_k \}\\ =(-1)^{i-1}\sum_{j=0}^{i-1}(-1)^j\times f[j]\times \min_{k=j+1}^i \{a_k\}$

$dp[i]=-\sum_{j=0}^{i-1} dp[j]\times \min_{k=j+1}^i \{a_k\}$

$ans=dp[n]\times (-1)^n$

## Code

#include <bits/stdc++.h>
using namespace std;

#define LL long long

template<typename elemType>
elemType X = 0, w = 0; char ch = 0;
while (!isdigit(ch)) { w |= ch == '-';ch = getchar(); }
while (isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar();
T = (w ? -X : X);
}

const LL MOD = 998244353;
LL a[200010], dp[200010], s[200010], pre[200010];
int n, top;

LL pre_sum(int L, int R) { return pre[R] - (L ? pre[L - 1] : 0); }

int main() {
for (int i = 1;i <= n;++i)
dp[0] = pre[0] = 1;
LL sum = 0;
for (int i = 1;i <= n;++i) {
while (top && a[s[top]] >= a[i]) {
sum = (sum - a[s[top]] * pre_sum(s[top - 1], s[top] - 1) % MOD) % MOD;
--top;
}
s[++top] = i;
sum = (sum + a[i] * pre_sum(s[top - 1], s[top] - 1)) % MOD;
dp[i] = ((MOD - sum) % MOD + MOD) % MOD;
pre[i] = (pre[i - 1] + dp[i]) % MOD;
}
LL ans = dp[n] * (n & 1 ? -1 : 1);
ans = (ans % MOD + MOD) % MOD;
printf("%I64d\n", ans);

return 0;
}

posted @ 2021-12-29 16:15  AE酱  阅读(118)  评论(0编辑  收藏  举报