1 条题解
-
0
自动搬运
来自洛谷,原作者为

Alex_Wei
**搬运于
2025-08-24 22:49:10,当前版本为作者最后更新于2023-09-17 14:46:44,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
P9522 [JOISC2022] 错误拼写
考虑 的等价条件。模拟字典序比较的过程:
- 若 ,那么要么 全部相等,要么 ,其中 是从 开始第一个不等于 的位置。
- 若 ,那么要么 全部相等,要么 ,其中 是从 开始第一个不等于 的位置。
考虑从后往前 DP,设 表示 的方案数。计算 时,枚举 表示 相等且 ,枚举 。考虑什么情况下 可以从 转移过来:如果存在 要求 ,那么 不能小于 ;若要求 ,那么 不能大于 。
设 ,则:
-
当有限制 时,在 转移到 之前的位置时,必须有 。
-
当有限制 时,在 转移到 之前的位置时,必须有 。
这说明,固定了 之后,随着 不断向前移动,存在一个时刻使得 不再能产生 的贡献,也存在一个时刻使得 不再能产生 的贡献。
设 表示 对之前的位置的每个 产生的贡献。枚举到 时,考虑所有和 有关的限制 ()
- 若限制 ,那么对于所有 且仍产生 的贡献的 ,将它 的贡献从 中去掉,即令 减去 。
- 若限制 ,那么对于所有 且仍产生 的贡献的 ,将它 的贡献从 中去掉,即令 减去 。
更新 之后有 ,其中 表示 均相等的情况。统计 对 的贡献: 加上 。
用链表或栈维护两种情况仍产生贡献的 ,时间复杂度 。
#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 */
- 1
信息
- ID
- 9070
- 时间
- 3500ms
- 内存
- 1024MiB
- 难度
- 6
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者