CF1327F AND Segments

CF1327F AND Segments

这题好像有点简单。

肯定先拆位,限制转化为两种:

  • 强制 $[l_i,r_i] $全为1
  • 强制 $[l_i,r_i] $不全为1

对于第一种限制,这时候 \([l_i,r_i]\) 已经确定了,所以可以直接差分一下直接把这一部分的 \(a\) 求出来,剩下的 \(a\) 只需考虑第二种限制。

维护 \(L_i\) 表示满足最小的位置 \(p\) 使得 \([p,i)\) 可以全部为 \(1\),设 \(f_i\) 表示最后一个填的位置是 \(i\),已经满足了右端点在 \([1, i]\) 内的限制的方案数。那么转移是很简单的。

\[f_i = \sum_{L_{i - 1} < k < i} f_k \]

这个直接用前缀和维护一下就可以了。

详情

#include <cstdio>
#include <iostream>
#define LL long long
using namespace std;
template <typename T>
inline void read(T &x) {
	x = 0; int f = 0; char ch = getchar();
	for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
	for(; isdigit(ch); ch = getchar()) x = (x << 3) + (x << 1) + (ch ^ 48);
	if(f) x = ~x + 1;
}
const int N = 5e5 + 10;
const int P = 998244353;
int n, m, k;
int l[N], r[N], v[N], pos[N];
int posl[N], posr[N];
int a[N], L[N];
int sum[N], f[N];
int calc(int p) {
	for(int i = 1; i <= n; ++i) a[i] = pos[i] = 0;
	for(int i = 1; i <= m; ++i) 
		if(v[i] >> p & 1) ++a[l[i]], --a[r[i] + 1];
	for(int i = 1; i <= n; ++i)
		a[i] += a[i - 1];
	int tot = 0;
	for(int i = 1; i <= n; ++i) {
		if(a[i] == 0) pos[i] = ++tot;
		else a[i] = 1;
		a[i] += a[i - 1];
	}
	for(int i = n; i >= 1; --i) 
		if(!pos[i]) posr[i] = posr[i + 1];
		else posr[i] = pos[i];
	for(int i = 1; i <= n; ++i)
		if(!pos[i]) posl[i] = posl[i - 1];
		else posl[i] = pos[i]; 
	for(int i = 1; i <= tot; ++i) L[i] = 0;
	for(int i = 1; i <= m; ++i) {
		if(v[i] >> p & 1) continue;
		if(a[r[i]] - a[l[i] - 1] == r[i] - l[i] + 1) return 0; 
		L[posl[r[i]]] = max(L[posl[r[i]]], posr[l[i]]);
	}
	for(int i = 1; i <= tot; ++i)
		L[i] = max(L[i], L[i - 1]);
	f[0] = sum[0] = 1;
	for(int i = 1; i <= tot; ++i)
		f[i] = (sum[i - 1] - (L[i - 1] <= 0 ? 0 : sum[L[i - 1] - 1]) + P) % P,
		sum[i] = (sum[i - 1] + f[i]) % P;
	int res = 0;
	for(int i = L[tot]; i <= tot; ++i)
		res = (res + f[i]) % P;
	return res;
}
int main() {
	read(n), read(k), read(m);
	for(int i = 1; i <= m; ++i)
		read(l[i]), read(r[i]), read(v[i]);
	LL ans = 1;
	for(int p = 0; p < k; ++p)
		ans = ans * calc(p) % P;
	printf("%lld\n",ans);
}
posted @ 2023-01-03 16:41  DCH233  阅读(29)  评论(0编辑  收藏  举报