P9522 [JOISC2022] 错误拼写
P9522 [JOISC2022] 错误拼写
考虑
- 若
i < j ,那么要么s_{i\sim j} 全部相等,要么s_i > s_p ,其中p 是从i 开始第一个不等于s_i 的位置。 - 若
i > j ,那么要么s_{j\sim i} 全部相等,要么s_j < s_p ,其中p 是从j 开始第一个不等于s_j 的位置。
考虑从后往前 DP,设
设
-
当有限制
T_u\leq T_v 时,在u < i'\leq v 转移到u 之前的位置时,必须有j > j' 。 -
当有限制
T_u\geq T_v 时,在u < i'\leq v 转移到u 之前的位置时,必须有j < j' 。
这说明,固定了
设
- 若限制
T_u\leq T_v ,那么对于所有u < i'\leq v 且仍产生j < j' 的贡献的i' ,将它j < j' 的贡献从h 中去掉,即令h_j 减去\sum_{j < j'} f_{i', j'} 。 - 若限制
T_u\geq T_v ,那么对于所有u < i' \leq v 且仍产生j > j' 的贡献的i' ,将它j > j' 的贡献从h 中去掉,即令h_j 减去\sum_{j > j'} f_{i', j'} 。
更新
用链表或栈维护两种情况仍产生贡献的
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using LL = __int128_t;
using ui = unsigned int;
using ull = unsigned long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
using pdi = pair<double, int>;
#define ppc(x) __builtin_popcount(x)
#define clz(x) __builtin_clz(x)
bool Mbe;
// mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());
mt19937 rnd(20060130);
int rd(int l, int r) {return rnd() % (r - l + 1) + l;}
constexpr int mod = 1e9 + 7;
void addt(int &x, int y) {x += y, x >= mod && (x -= mod);}
int add(int x, int y) {return x += y, x >= mod && (x -= mod), x;}
char buf[1 << 20], *p1 = buf, *p2 = buf;
#define getc() (p1 == p2 && (p2 = (p1 = buf) + \
fread(buf, 1, 1 << 20, stdin), p1 == p2) ? EOF : *p1++)
inline int read() {
int x = 0;
char s = getc();
while(!isdigit(s)) s = getc();
while(isdigit(s)) x = x * 10 + s - '0', s = getc();
return x;
}
#define putc(x) putchar(x)
inline void print(ui x) {
if(x >= 10) print(x / 10);
putc(x % 10 + '0');
}
// ---------- templates above ----------
constexpr int N = 5e5 + 5;
int n, m, f[N][27], h[27];
int a[N], b[N], x[N], y[N];
vector<int> e[N], g[N];
void mian() {
cin >> n >> m;
for(int i = 1; i <= n; i++) a[i] = b[i] = i + 1;
for(int i = 1; i <= m; i++) {
int x, y;
cin >> x >> y;
if(x < y) e[x].push_back(y);
else g[y].push_back(x);
}
for(int i = n; i; i--) {
for(int it : e[i]) {
for(int p = a[i]; p <= it; p = a[p]) {
vector<int> s(27);
for(int j = 1; j <= 26; j++) s[j] = add(s[j - 1], f[p][j]);
for(int j = 1; j <= 26; j++) addt(h[j], mod - add(s[26], mod - s[j]));
a[i] = a[p];
}
}
for(int it : g[i]) {
for(int p = b[i]; p <= it; p = b[p]) {
vector<int> s(27);
for(int j = 1; j <= 26; j++) s[j] = add(s[j - 1], f[p][j]);
for(int j = 1; j <= 26; j++) addt(h[j], mod - s[j - 1]);
b[i] = b[p];
}
}
int sum = 0;
for(int j = 1; j <= 26; j++) {
f[i][j] = h[j] + 1;
addt(h[j], mod - f[i][j]);
addt(sum, f[i][j]);
}
if(i == 1) cout << sum << "\n";
for(int j = 1; j <= 26; j++) addt(h[j], sum);
}
}
bool Med;
int main() {
fprintf(stderr, "%.3lf MB\n", (&Mbe - &Med) / 1048576.0);
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
#ifdef ALEX_WEI
FILE* IN = freopen("1.in", "r", stdin);
FILE* OUT = freopen("1.out", "w", stdout);
#endif
int T = 1;
while(T--) mian();
fprintf(stderr, "%d ms\n", int(1e3 * clock() / CLOCKS_PER_SEC));
return 0;
}
/*
g++ a.cpp -o a -std=c++14 -O2 -DALEX_WEI
*/