Educational Codeforces Round 83 --- F. AND Segments

Posted embiid

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Educational Codeforces Round 83 --- F. AND Segments相关的知识,希望对你有一定的参考价值。

解法

根据题意,就是拆位,每一位上有两种限制,在[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][1sim l-1])就都会remove成0,成为非法情况
最后每位(Ans=sum_{i=0}^n f[n][i])
如果暴力做的话每一位是(n^{2})
但是我们考虑,每次remove操作是有后延性的,我们可以同时进行,不用暴力清除(1sim 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;
	
} 







以上是关于Educational Codeforces Round 83 --- F. AND Segments的主要内容,如果未能解决你的问题,请参考以下文章

Educational Codeforces Round 7 A

Educational Codeforces Round 7

Educational Codeforces Round 90

Educational Codeforces Round 33

Codeforces Educational Codeforces Round 54 题解

Educational Codeforces Round 27