Processing math: 100%
Codeforces 1327F AND Segments

Codeforces 1327F AND Segments

题目链接

https://codeforces.com/contest/1327/problem/F

题目大意

m 个条件,(l_i, r_i, x_i) ,表示 a[l_i] \& a[l_i + 1] \& \dots \& a[r_i] = x_i。问有多少种填写长度为 n 的数组 a 的方法,使得满足这 m 个条件且有 0 \le a_i < 2^k

题目分析

显然对于每一位都可以分开考虑,如果有 (l, r) 的答案是 1,那么显然 lr 所有的数字都需要填 1。否则的话,可以考虑使用 DP 来解决问题。

f[i] 是点 i0 的答案个数。对于一段 (l, r) 的限制,那么显然 r + 1 的转移会受到限制,因为 lr 之间必须有一个 0 。因此可以使用双指针和前缀和来维护转移,这样一来就可以解决问题了。

代码

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
#include <bits/stdc++.h>
using namespace std;
const int mod = 998244353;
const int maxn = 5e5 + 5;
int n, m, k;
int L[maxn], R[maxn], X[maxn];
int sa[maxn];
int g[maxn], h[maxn];
long long sum[maxn], f[maxn];
long long calc(long long l, long long r){
if(l == 0) return sum[r];
return (sum[r] - sum[l - 1] + mod) % mod;
}
int main(){
int i, j;
long long ans = 1;
scanf("%d%d%d", &n, &k, &m);
for(i=1;i<=m;i++){
scanf("%d%d%d", &L[i], &R[i], &X[i]);
}
for(j=0;j<k;j++){
for(i=1;i<=n+1;i++) sa[i] = sum[i] = f[i] = h[i] = 0;
for(i=1;i<=m;i++){
if((X[i] >> j) & 1){
sa[L[i]]++;
sa[R[i] + 1]--;
}
}
for(i=1;i<=n;i++) sa[i] += sa[i - 1];
for(i=1;i<=m;i++){
if(!((X[i] >> j) & 1)){
h[R[i] + 1] = max(h[R[i] + 1], L[i]);
}
}
f[0] = 1;
sum[0] = 1;
int l = 0;
for(i=1;i<=n;i++){
l = max(h[i], l);
sum[i] = sum[i - 1];
if(sa[i]) continue;
f[i] = calc(l, i - 1);
sum[i] = (sum[i] + f[i]) % mod;
}
l = max(h[n + 1], l);
ans = ans * (calc(l, n)) % mod;
}
printf("%lld\n", ans);
return 0;
}
#include <bits/stdc++.h> using namespace std; const int mod = 998244353; const int maxn = 5e5 + 5; int n, m, k; int L[maxn], R[maxn], X[maxn]; int sa[maxn]; int g[maxn], h[maxn]; long long sum[maxn], f[maxn]; long long calc(long long l, long long r){ if(l == 0) return sum[r]; return (sum[r] - sum[l - 1] + mod) % mod; } int main(){ int i, j; long long ans = 1; scanf("%d%d%d", &n, &k, &m); for(i=1;i<=m;i++){ scanf("%d%d%d", &L[i], &R[i], &X[i]); } for(j=0;j<k;j++){ for(i=1;i<=n+1;i++) sa[i] = sum[i] = f[i] = h[i] = 0; for(i=1;i<=m;i++){ if((X[i] >> j) & 1){ sa[L[i]]++; sa[R[i] + 1]--; } } for(i=1;i<=n;i++) sa[i] += sa[i - 1]; for(i=1;i<=m;i++){ if(!((X[i] >> j) & 1)){ h[R[i] + 1] = max(h[R[i] + 1], L[i]); } } f[0] = 1; sum[0] = 1; int l = 0; for(i=1;i<=n;i++){ l = max(h[i], l); sum[i] = sum[i - 1]; if(sa[i]) continue; f[i] = calc(l, i - 1); sum[i] = (sum[i] + f[i]) % mod; } l = max(h[n + 1], l); ans = ans * (calc(l, n)) % mod; } printf("%lld\n", ans); return 0; }
#include <bits/stdc++.h>

using namespace std;

const int mod = 998244353;
const int maxn = 5e5 + 5;

int n, m, k;

int L[maxn], R[maxn], X[maxn];

int sa[maxn];

int g[maxn], h[maxn];
long long sum[maxn], f[maxn];

long long calc(long long l, long long r){
	if(l == 0) return sum[r];
	return (sum[r] - sum[l - 1] + mod) % mod;
}

int main(){
	int i, j;
	long long ans = 1;
	
	scanf("%d%d%d", &n, &k, &m);
	
	for(i=1;i<=m;i++){
		scanf("%d%d%d", &L[i], &R[i], &X[i]);
	}
	
	for(j=0;j<k;j++){
		for(i=1;i<=n+1;i++) sa[i] = sum[i] = f[i] = h[i] = 0;
		for(i=1;i<=m;i++){
			if((X[i] >> j) & 1){
				sa[L[i]]++;
				sa[R[i] + 1]--;
			}
		}
		for(i=1;i<=n;i++) sa[i] += sa[i - 1];
		
		for(i=1;i<=m;i++){
			if(!((X[i] >> j) & 1)){
				h[R[i] + 1] = max(h[R[i] + 1], L[i]);
			}
		}
		
		f[0] = 1;
		sum[0] = 1;
		int l = 0;
		
		for(i=1;i<=n;i++){
			l = max(h[i], l);
			sum[i] = sum[i - 1];
			if(sa[i]) continue;
			f[i] = calc(l, i - 1);
			sum[i] = (sum[i] + f[i]) % mod;
		}
		
		l = max(h[n + 1], l);
		ans = ans * (calc(l, n)) % mod;
	}
	
	printf("%lld\n", ans);
	
	return 0;
}

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据