Interesting-Array-CodeForces-482B

又是二进制相关的问题

注意如下性质

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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值