首页 > 其他分享 >[题解] CF1327F AND Segments

[题解] CF1327F AND Segments

时间:2023-11-11 19:35:43浏览次数:43  
标签:限制 CF1327F int 题解 Segments Read MAXN forall sum

AND Segments

有 \(m\) 个限制 \((l, r, x)\)。
要计算满足以下条件的长度为 \(n\) 的序列 \(a\) 的数量:

  • \(\forall i \in [1, n], 0 \le a_i < 2^k\)。
  • \(\forall i \in [1, m], a_{l_i} \operatorname{and} a_{l_i + 1} \operatorname{and} \cdots \operatorname{and} a_{r_i} = x\)。
    \(n, m \le 10^5, k \le 30\)。

首先要想到分别计算二进制下每一位的方案数然后乘起来就是答案。

然后现在问题就变成了有若干个限制表示 \(a\) 在 \([l_i, r_i]\) 中的数的按位与为 0/1,要计算 01 序列 \(a\) 的数量。

将每个限制挂到右端点上,然后 dp 计算方案数。

因为是按位与,所以值只与最后一个 0 的位置有关。所以设 \(f_{i, j}\) 表示考虑了前 \(i\) 个位置,最后一个 0 的位置为 \(j\) 时的方案数。

可以发现,对于每条限制,其实是限制了最后一个 0 的位置一定是在一个区间里。具体地说,如果有一个限制 \((l, r, 0)\),就说明在 \([l, r]\) 一定有一个 0,也就是当 \(i = r\) 时,最后一个 0 一定是在 \([l, r]\) 中;如果有一个限制 \((l, r, 1)\),就说明在 \([l, r]\) 中一定全是 1,也就是当 \(i = r\) 时,最后一个 0 一定是在 \([0, l - 1]\) 中。

转移就是先考虑没有限制的时候:对当前位置填 0 还是填 1 分别考虑:

\[f_{i, j} \leftarrow f_{i - 1, j} \\ f_{i, i} \leftarrow \sum_{j \in [0, i)} f_{i - 1, j} \]

再考虑加上限制:

  • 如果有一个限制 \((l, r, 0)\):

\[\forall j \in [0, l), f_{r, j} = 0 \]

  • 如果有一个限制 \((l, r, 1)\):

\[\forall i \in [l, r], f_{i, i} = 0 \]

把第一维滚掉之后我们要做的就是单点改、前缀推平成 0、求前缀和,这个记一下前缀和和最长前缀推平长度就行了。

时间复杂度 \(O(nk)\)。

constexpr int MAXN = 5e5 + 9;
int n, k, m, ans = 1, f[MAXN], a[MAXN];
vector<pair<int, int> > lim[MAXN];

int calc(int bit) {
	for (int i = f[0] = 1; i <= n; i ++) f[i] = 0, a[i] = 0;
	for (int r = 1; r <= n; r ++) for (auto [l, x] : lim[r])
		if (x >> bit & 1) a[l] ++, a[r + 1] --;
	for (int i = 1; i <= n; i ++) a[i] += a[i - 1];
	int sum = 1, pre = 0;
	for (int i = 1; i <= n; i ++) {
		int pos = 0;
		for (auto [l, x] : lim[i])
			if ((x >> bit & 1) == 0) cmax(pos, l);
		if (!a[i]) f[i] = sum, cadd(sum, f[i]);
		while (pre < pos) cdel(sum, f[pre]), pre ++;
	}
	return sum;
}

void slv() {
	n = Read<int>(), k = Read<int>(), m = Read<int>();
	for (int i = 1; i <= m; i ++) {
		int l = Read<int>(), r = Read<int>(), x = Read<int>();
		lim[r].emplace_back(l, x);
	}
	for (int i = 0; i < k; i ++) cmul(ans, calc(i));
	Write(ans, '\n');
	return;
}

标签:限制,CF1327F,int,题解,Segments,Read,MAXN,forall,sum
From: https://www.cnblogs.com/definieren/p/17826217.html

相关文章

  • 【洛谷 P1035】[NOIP2002 普及组] 级数求和 题解(循环)
    [NOIP2002普及组]级数求和题目描述已知:。显然对于任意一个整数,当足够大的时候,。现给出一个整数,要求计算出一个最小的,使得。输入格式一个正整数。输出格式一个正整数。样例#1样例输入#11样例输出#12提示【数据范围】对于的数据,。【题目来源】NOIP2002普及组第一题......
  • AT_agc057_e 题解
    AT_agc057_e[0]约定\(r_i=\sum\limits_{j=1}^{m}[A_{i,j}\lek]\)\(r^{'}_i=\sum\limits_{j=1}^{m}[B_{i,j}\lek]\)\(c_j=\sum\limits_{i=1}^{n}[A_{i,j}\lek]\)\(c^{'}_j=\sum\limits_{i=1}^{n}[B_{i,j}\lek]\)[1]......
  • [题解] AT_dp_w Intervals
    Intervals有\(m\)条形如\((l,r,a)\)的限制,表示如果\(s_{[l,r]}\)中有1就会有\(a\)的价值。你要求长度为\(n\)的01串的价值的最大值。\(n,m\le2\times10^5\)。将每个限制挂到右端点上,在右端点处计算贡献。然后我们就只关心最后一个1出现的位置了。......
  • 转 问题解决:记录一次Linux服务器根目录突然爆满
    一般跟目录满了,可以重点关注/var这个目录 一、出问题了过了个双休来到公司,同时发现Linux终端的服务器状态中根目录空间直接爆满100%,周五走之前根目录仅仅使用了59%,同时项目服务的后台不停的有日志打印,而且测试的小伙伴说系统登录不上去了。下面记录一下个人排查并解决这个问题......
  • CF1485F Copy or Prefix Sum 题解
    思路考虑\(a_i\)要么是\(b_i\)要么是\(b_i-s\)。考虑\(s\)代表着什么。它是\(a\)的前缀和。那么必然是往前一段\(b\)的和。因为每个\(b\)代表着要么是这一位的\(a\)或者前面所有的\(a\)。考虑设\(f_i\)为这个位置填\(b_i\)的方案数。\(g_i\)为这个......
  • [POI2011] SMI-Garbage 题解
    题目链接显然,对于初始颜色与目标颜色不同的边,我们需要走过奇数次;对于初始颜色与目标颜色相同的边,我们需要走过偶数次。对于只有偶数边的情况,这种情况下不走就行;对于只有奇数边;可以理解为每条边只能经过一次,就是欧拉路径问题,并且考虑这题的特殊性质,如果一个图是由若干个简单环构......
  • CSP-S2019 江西 题解
    为什么有\(5\)道题?[CSP-S2019江西]和积和简单化一下式子:\[(n+1)\times\sumA_i\timesB_i-(\sumA_i)\times(\sumB_i)\]其中\(A,B\)都是前缀和。[CSP-S2019江西]网格图naive的kruskal是很naive的,所以需要一点简单的优化。考虑其本质过程就是按照......
  • CF1485E Move and Swap 题解
    不要什么脑子的带\(log\)做法。思路考虑\(dp_{i,j}\)表示红点到\(i\),蓝点到\(j\)的最大权值。那么有:\[dp_{i,j}=\max(dp_{fa_i,pre},dp_{fa_j,pre})+|a_i-a_j|\]其中\(pre\)是任意一个上一层节点。发现第二维没有用。可以优化:\[dp_i=\max(dp_{fa_i}+\max(|a_i-a_......
  • APISIX源码安装问题解决
    官网手册的安装语句:curlhttps://raw.githubusercontent.com/apache/apisix/master/utils/install-dependencies.sh-sL|bash-执行install-dependencies.sh报如下错误:Transactioncheckerror:file/usr/share/gcc-4.8.2/python/libstdcxx/v6/printers.pyfrominstal......
  • 苏格拉底问答、实践过程截图、遇到问题解决问题截图,代码链接
    #include<stdio.h>#include<stdlib.h>#include<string.h>#include<unistd.h>#include<signal.h>#include<setjmp.h> //foralongjumpjmp_bufenv;//forsavinglonjmpenviromentintcount=0;voidhandler(intsig,......