解法
根据题意,就是拆位,每一位上有两种限制,在[l,r]上全1或者存在0。
那我们考虑对每一位单独操作,f[i][j]表示处理了前i个位置,上次出现0是在j位置。
对于每一个可以放0的位置,\(f[i][i]=\sum_{j=1}^{i-1} f[i-1][j]\)
对于每个位置r,如果存在限制[l,r]存在0,那么\(f[r][1\sim l-1]\)就都会remove成0,成为非法情况
最后每位\(Ans=\sum_{i=0}^n f[n][i]\)
如果暴力做的话每一位是\(n^{2}\)
但是我们考虑,每次remove操作是有后延性的,我们可以同时进行,不用暴力清除\(1\sim l-1\)
这样额外记录一个\(sum=\sum_{j=1}^{i} f[i][j]\)就可以了
#include <bits/stdc++.h>
#define ll long long
#define lson rt << 1
#define rson rt << 1 | 1
using namespace std;
const ll mol = 998244353;
const int maxn = 5e5;
int to[maxn + 11],l[maxn + 11],r[maxn + 11],x[maxn + 11],a[maxn + 11];
ll f[maxn + 11];
ll sub(ll a,ll b) { a -= b; if (a < 0) a += mol; return a; }
int main(){
ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n,k,m; cin >> n >> k >> m;
for (int i = 1; i <= m; i++) {
cin >> l[i] >> r[i] >> x[i];
}
ll ans = 1;
for (int j = 0; j < k; j++) {
for (int i = 1; i <= n; i++) a[i] = 0,to[i] = 0;
for (int i = 1; i <= m; i++) {
if (x[i] & (1 << j)) {
a[l[i]]++; a[r[i] + 1]--;
}
else to[r[i]] = max(to[r[i]] , l[i]);
}
ll sum = 1;
f[0] = 1;
int ind = 0;
for (int i = 1; i <= n; i++) {
a[i] += a[i - 1];
if (a[i]) f[i] = 0;
else{
f[i] = sum;
sum = sum * 2 % mol;
}
if (!to[i]) continue;
while (ind < to[i]) { sum = sub(sum , f[ind]); ind++; }
}
ans = ans * sum % mol;
}
cout << ans << endl;
}