CF1327F AND Segments Sol

好久没有见到这么喵喵的题目了!

考虑拆位乘法原理算答案即可。对于每一位,如果与为 1 那么有整个区间都是 1,如果与为 0 就考虑记录每一个点 i 最晚必须在哪个点放一个 1,记为 posi。这里可以在输入区间的时候计算,然后线性计算取 max 即可,比较简单。

DP 转移非常的喵!设 dpi,j 表示当前枚举到第 i 个数,最后一个 0 填在第 j 个位置上的方案数。

  • j<posi,有 dpi,j=0
  • posij<i,有 dpi,j=dpi1,j。(默认在第 i 个位置填 1,所以不变)
  • j=i,若当前位置必须填 1,则 dpi,j=0;否则有 dpi,j=k=posii1dpi1,k

考虑到所有操作都是从 i1i,不妨直接在原数组上开刀。

第一个操作,直接维护一个左指针区间推成 0

第二个操作,并没有什么变化。

第三个操作,实时记录和即可。

没了。

#include <bits/stdc++.h>
#define int long long
using namespace std;

const int N = 5e5 + 10, Mod = 998244353;
int n, k, m, l[N], r[N], x[N], dp[N], pos[N], sum[N];

signed main() {
    ios_base::sync_with_stdio(false); cin.tie(0), cout.tie(0);
    cin >> n >> k >> m; int res = 1;
    for (int i = 1; i <= m; ++i) cin >> l[i] >> r[i] >> x[i];
    for (int bit = 0; bit < k; ++bit) {
        for (int i = 1; i <= n + 1; ++i) sum[i] = pos[i] = 0;
        for (int i = 1; i <= m; ++i) {
            if (x[i] >> bit & 1) ++sum[l[i]], --sum[r[i] + 1];
            else pos[r[i] + 1] = max(pos[r[i] + 1], l[i]);
        }
        for (int i = 2; i <= n + 1; ++i)
            sum[i] += sum[i - 1], pos[i] = max(pos[i], pos[i - 1]);
        dp[0] = 1; int tot = 1, key = 0;
        for (int i = 1; i <= n + 1; ++i) {
            while (key < pos[i]) (((tot -= dp[key]) %= Mod) += Mod) %= Mod, dp[key++] = 0;
            dp[i] = sum[i]? 0 : tot, (tot += dp[i]) %= Mod;
        }
        (res *= dp[n + 1]) %= Mod;
    }
    return cout << res << endl, 0;
}
posted @   MistZero  阅读(14)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示