题目大意:有一天,xyz1048576 想到了一个模型:一个长度为 n 的非负整数序列 x,满足 m 个条件:第 i 个条件为 x[li] or x[li+1] or … or x[ri]=pi。他想知道是否存在一个序列满足条件,如果存在,他还要构造出一个这样的序列

考虑或的条件:有一为真即为真

也就是说,这么多数二进制拆分之后,每一位都为零的话,最后的那个p的那个位置才是零,只要有一位不是零,最后的p一定不是零

观察发现,如果p在二进制下有这一位的话,那么这期间所有数字只有一个为1即可,这启发我们对零来操作

差分?

然后就不太透彻了,等待_plxer大佬来补坑…

补坑:

用f数组来维护零的个数,sum数组来维护一的个数

在读入的时候,我们把p按照二进制位拆分,其中\(f[i][j]​\)表示第j位出现的零的个数

如果为零也就意味着这一位没有零,也就是说,对应到原序列里面这一位是有数的,所以num数组统计上他这一位的贡献

考虑不合法的判断:这个区间内出现了多于\(p_{二进制}\)的一的个数,或者少了

总之就是\(sum[r[i]-sum[l[i] - 1]\)不为零

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#define int long long
using namespace std;

const int N = 1e5 + 66;

int n, m;
int l[N], r[N], p[N], num[N];
int f[N][66], sum[N][66];

signed main()
{
n = read(), m = read();

for (int i = 1; i <= m; ++ i)
{
l[i] = read(), r[i] = read(), p[i] = read();
for (int j = 0; j <= 30; ++ j)
{
if (! ((p[i] >> j) & 1))
{
++ f[l[i]][j];
-- f[r[i] + 1][j];
}
}
}

for (int i = 1; i <= n; ++ i)
{
for (int j = 0; j <= 30; ++ j)
{
f[i][j] += f[i - 1][j];
if (f[i][j] == 0) sum[i][j] += 1, num[i] += (1 << j);
sum[i][j] += sum[i - 1][j];
}
}

for (int i = 1; i <= m; ++ i)
for (int j = 0; j <= 30; ++ j)
if ((p[i] >> j) & 1)
if (sum[r[i]][j] - sum[l[i] - 1][j] != 0) return puts("No"), 0;

puts("Yes");
for (int i = 1; i <= n; ++ i) put(num[i]);
return 0;
}