又是二进制相关的问题
注意如下性质
val[rt] = K 者定有val[rt<<1] & val[rt<<1|1] 为K
这是判断是否合法的依据
一开始想的做法是动态插入,事实上会遇到很多难以处理的问题
看了题解知道正解是将所有约束条件插入,再查询是否合法
显然可以知道对于区间[L,R] 的二进制每一位至少为K的二进制,易得这里是取到了区间最小的解
注意使用lazy tag
#include <bits/stdc++.h>
using namespace std;
#define sci(a) scanf("%d",&a)
const int MAX_N = 1e5 + 100;
int L[MAX_N<<2],R[MAX_N<<2];
int vs[MAX_N<<2];
bool flag= true;
int a[MAX_N],b[MAX_N],c[MAX_N];
void build(int rt,int l,int r) {
L[rt] = l;
R[rt] = r;
vs[rt] = 0;
if (l == r) return;
int mid = l + (r - l) / 2;
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
}
void push_down(int rt) {
if (L[rt] == R[rt]) return;
if (vs[rt]) {
vs[rt<<1] |= vs[rt];
vs[rt<<1|1] |= vs[rt];
}
}
void update(int rt,int a,int b,int q) {
push_down(rt);
if (a <= L[rt] && R[rt] <= b) {
vs[rt] |= q;
return;
}
int mid = L[rt] + (R[rt] - L[rt]) / 2;
if (a <= mid)
update(rt<<1,a,b,q);
if (mid < b)
update(rt<<1|1,a,b,q);
}
int query(int rt,int a,int b) {
push_down(rt);
int ans = -1;
if (a <= L[rt] && R[rt] <= b) {
ans &= vs[rt];
return ans;
}
int mid = L[rt] + (R[rt] - L[rt]) / 2;
if (a <= mid)
ans &= query(rt<<1,a,b);
if (mid < b)
ans &= query(rt<<1|1,a,b);
return ans;
}
void output(int rt) {
push_down(rt);
if (L[rt] == R[rt]) {
if (L[rt] == 1) {
printf("%d",vs[rt]);
} else {
printf(" %d",vs[rt]);
}
return;
}
output(rt<<1);
output(rt<<1|1);
}
int main() {
int N,M;
sci(N); sci(M);
build(1,1,N);
for (int i = 0;i < M;i++) {
sci(a[i]); sci(b[i]); sci(c[i]);
update(1,a[i],b[i],c[i]);
}
for (int i = 0;i < M;i++) {
if (flag && query(1,a[i],b[i]) != c[i]) {
flag = false;
}
}
if (flag) {
printf("YES\n");
output(1);
} else {
printf("NO\n");
}
return 0;
}