Codeforces 482B Interesting Array(线段树)
题目大意:给定一个长度为N的数组,现在有M个限制,每个限制有l,r,q,表示从a[l]~a[r]取且后的数一定为q,问是否有满足的数列。
考虑维护 30颗线段树 每个代表这位二进制 0 1
区间修改 区间查 这线段树代表的二进制位 覆盖区间 与 q 这位二进制 是一样的
如果q 是 0 但是 这树区间二进制 区间全是1 cout <<“NO”<< endl;
然后 我们光荣的T了
在仔细想想 一个树上之维护 一位 有点少 毕竟 二进制每一位也没有啥关系
一个树就完成了 毕竟int 存30位二进制没有啥压力
我们进行的区间覆盖,按位或运算,可以直接把三十颗线段树合到一棵,支持区间或修改,每次区间或上val[i];
最后 在& 回去 暴力对所有条件进行判断 不行就NO
这题就完成了
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 6;
int tree[maxn << 2], lazy[maxn << 2];
inline void push_up(int rt) {
tree[rt] = tree[rt << 1] & tree[rt << 1 | 1];
}
inline void push_down(int rt) {
lazy[rt << 1] |= lazy[rt];
lazy[rt << 1 | 1] |= lazy[rt];
tree[rt << 1] |= lazy[rt];
tree[rt << 1 | 1] |= lazy[rt];
lazy[rt] = 0;
}
void updata(int L, int R, int l, int r, int rt, int val) {
if(L <= l && R >= r) {
tree[rt] |= val;
lazy[rt] |= val;
return ;
}
if(lazy[rt]) push_down(rt);
int mid = l + r >> 1;
if(L <= mid) updata(L, R, l, mid, rt << 1, val);
if(R > mid) updata(L, R, mid + 1, r, rt << 1 | 1, val);
push_up(rt);
}
int query(int L, int R, int l, int r, int rt) {
if(L <= l && R >= r) {
return tree[rt];
}
if(lazy[rt]) push_down(rt);
int mid = l + r >> 1;
int res = (1 << 31) - 1;
if(L <= mid) res &= query(L, R, l, mid, rt << 1);
if(R > mid) res &= query(L, R, mid + 1, r, rt << 1 | 1);
return res;
}
int l[maxn], r[maxn], val[maxn];
signed main() {
int n, m, flag = 0;
scanf("%d %d", &n, &m);
for(int i = 1; i <= m; i ++) {
scanf("%d %d %d", &l[i], &r[i], &val[i]);
updata(l[i], r[i], 1, n, 1, val[i]);
}
for(int i = 1; i <= m; i ++) {
if(query(l[i], r[i], 1, n, 1) != val[i]) {
flag = 1;
break;
}
}
if(flag) puts("NO");
else {
puts("YES");
for(int i = 1; i <= n; i ++) {
if(i != 1) printf(" ");
printf("%d", query(i, i, 1, n, 1));
}
puts("");
}
return 0;
}