专栏文章

JOISC2022 错误拼写 Sol

P9522题解参与者 4已保存评论 4

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
4 条
当前快照
1 份
快照标识符
@mir05x1r
此快照首次捕获于
2025/12/04 13:35
3 个月前
此快照最后确认于
2025/12/04 13:35
3 个月前
查看原文
实在是绷不住了,做 JOISC 做到梦熊炼石原题,这下这下了。
限制 TuTv (u<v)T_u\le T_v\ (u<v) 告诉你啥呢,告诉你这 [u,v][u, v] 这个区间要么全部相等,要么第一个相邻不同的位置是左边大于右边;u>vu>v 就是反过来,要么相等要么第一个相邻不同的位置左边小于右边。
考虑 dp,fi,jf_{i,j} 表示考虑了 [i,n][i,n]ii 这个位置填的 jj 这个字符。如果暴力转移就是枚举下一个不同的位置,判断合不合法并计算贡献。复杂度是 Θ(n2Σ)\Theta(n^2\Sigma)
你去想判断合不合法的过程是怎么样的,就是把所有左端点 i\ge i 的限制区间全扔下标上,进行一个判断。那我们发现你 ii 从右边来的时候,会增加一部分区间,改变一些位置的限制条件(即转移方式)。具体地,一个位置被转移的方式有:
  • 不被覆盖
  • 仅被 u<vu<v 的覆盖
  • 仅被 u>vu>v 的覆盖
  • 被两者同时覆盖
然后发现每个点的状态最多被改变 22 次。我们只要快速找到哪些点的覆盖状态发生了改变,用 set 维护每种状态的位置即可。复杂度 Θ(n(logn+Σ))\Theta(n(\log n+\Sigma))
CPP
signed main() {
	n = read(), m = read();
	rep(i, 1, m) {
		int x = read(), y = read(), f = 0;
		if (x == y) continue;
		if (x > y) swap(x, y), f ^= 1;
		p[x].push_back({y, f});
	}
	rep(j, 0, 25) f[n][j] = 1, ge[j] = 1;
	se.insert(n);
	per(i, n - 1, 1) {
		for (pii j : p[i]) {
			int l = i, r = j.fs, fl = j.sc;
			if (fl) {
				auto it = se.lower_bound(l + 1);
				while (it != se.end() && *it <= r) {
					s1.insert(*it);
					rep(k, 0, 25) g1[k] += f[*it][k], ge[k] -= f[*it][k];
					se.erase(it++);
				}
				it = s0.lower_bound(l + 1);
				while (it != s0.end() && *it <= r) {
					s2.insert(*it);
					rep(k, 0, 25) g0[k] -= f[*it][k];
					s0.erase(it++);
				}
			} else {
				auto it = se.lower_bound(l + 1);
				while (it != se.end() && *it <= r) {
					s0.insert(*it);
					rep(k, 0, 25) g0[k] += f[*it][k], ge[k] -= f[*it][k];
					se.erase(it++);
				}
				it = s1.lower_bound(l + 1);
				while (it != s1.end() && *it <= r) {
					s2.insert(*it);
					rep(k, 0, 25) g1[k] -= f[*it][k];
					s1.erase(it++);
				}
			}
		}
		int s = 0;
		rep(j, 0, 25) (s += ge[j]) %= mod;
		rep(j, 0, 25) f[i][j] += (s - ge[j] % mod + mod) % mod;
		s = 0;
		per(j, 25, 0) {
			(f[i][j] += s) %= mod;
			(s += g0[j] % mod) %= mod;
		}
		s = 0;
		rep(j, 0, 25) {
			(f[i][j] += s) %= mod;
			(s += g1[j]) %= mod;
		}
		rep(j, 0, 25) f[i][j]++, f[i][j] %= mod;
		se.insert(i);
		rep(j, 0, 25) ge[j] += f[i][j];
	}
	int ans = 0;
	rep(j, 0, 25) (ans += f[1][j]) %= mod;
	write(ans);
    return 0;
}

评论

4 条评论,欢迎与作者交流。

正在加载评论...