CF482B Interesting Array

题面

构建一个序列 a a a,满足 m m m条限制. 限制形如 &lt; l , r , q &gt; &lt;l,r,q&gt; <l,r,q>: a [ l ] a[l] a[l]& a [ l + 1 ] a[l+1] a[l+1]&…& a [ r − 1 ] a[r-1] a[r1]& a [ r ] = q a[r]=q a[r]=q;(此处&为位运算的 a n d and and操作).

题解

我们发现:

  • 如果 q q q的第 i i i位为 1 1 1,那么 a [ l ] , a [ l + 1 ] . . . a [ r ] a[l],a[l+1]...a[r] a[l],a[l+1]...a[r]的第 i i i位都为 1 1 1
  • 如果 q q q的第 i i i位为 0 0 0,那么 a [ l ] , a [ l + 1 ] . . . a [ r ] a[l],a[l+1]...a[r] a[l],a[l+1]...a[r]的第 i i i位至少有一个为 0 0 0

考虑将将所有二进制状态压缩在一个 i n t int int里,用线段树维护。
a [ 1 ] a[1] a[1] a [ n ] a[n] a[n]先设为 0 0 0
先满足第一个条件( a [ l ] , a [ l + 1 ] . . . a [ r ] a[l],a[l+1]...a[r] a[l],a[l+1]...a[r]的第 i i i位都为 1 1 1),用按位或运算将 a [ l ] , a [ l + 1 ] . . . a [ r ] a[l],a[l+1]...a[r] a[l],a[l+1]...a[r]的第 i i i位设成 1 1 1,最后扫一遍,做判断。

#include <bits/stdc++.h>
#define MAXN 100005
using namespace std;
int ans[MAXN];
inline int read(){
    int x=0,f=1;
    char ch=getchar();
    while (ch<'0'||ch>'9'){
        if (ch=='-') f=-1;
        ch=getchar();
    }
    while (ch>='0'&&ch<='9'){
        x=(x<<3)+(x<<1)+(ch^'0');
        ch=getchar();
    }
    return x*f;
}
namespace SegmentTree{
    struct node{
        int l,r;
        int val,tag;
    }tree[MAXN<<2];
    #define lc i<<1
    #define rc i<<1|1
    inline void pushup(int i){
        tree[i].val=tree[lc].val&tree[rc].val;
    }
    inline void pushdown(int i){
        if (tree[i].tag){
            tree[lc].tag|=tree[i].tag;
            tree[rc].tag|=tree[i].tag;
            tree[lc].val|=tree[i].tag;
            tree[rc].val|=tree[i].tag;
            tree[i].tag=0;
        }
    }
    void Build(int i,int l,int r){
        tree[i].l=l,tree[i].r=r;
        tree[i].val=tree[i].tag=0;
        if (l==r) return ;
        int mid=(l+r)>>1;
        Build(lc,l,mid);
        Build(rc,mid+1,r);
    }
    void Update(int i,int L,int R,int val){
        if (L<=tree[i].l&&tree[i].r<=R){
            tree[i].val|=val;
            tree[i].tag|=val;
            return ;
        }
        pushdown(i);
        int mid=(tree[i].l+tree[i].r)>>1;
        if (L<=mid) Update(lc,L,R,val);
        if (mid<R) Update(rc,L,R,val);
        pushup(i);
    }
    int Query(int i,int L,int R){
        if (L<=tree[i].l&&tree[i].r<=R){
            return tree[i].val;
        }
        pushdown(i);
        int mid=(tree[i].l+tree[i].r)>>1;
        if (L>mid) return Query(rc,L,R);
        else if (mid>=R) return Query(lc,L,R);
        else return Query(lc,L,R)&Query(rc,L,R);
    }
    void Out(int i){//记录结果
        if (tree[i].l==tree[i].r){
            ans[tree[i].l]=tree[i].val;
            return ;
        }
        pushdown(i);
        Out(lc);
        Out(rc);
    }
}
using namespace SegmentTree;
int ql[MAXN],qr[MAXN],qp[MAXN];
int main(){
    int n=read(),m=read();
    Build(1,1,n);
    for (register int i=1;i<=m;++i){
        ql[i]=read(),qr[i]=read(),qp[i]=read();
        Update(1,ql[i],qr[i],qp[i]);
    }
    Out(1);
    for (register int i=1;i<=m;++i){
        if (Query(1,ql[i],qr[i])!=qp[i]){
            puts("NO");
            return 0;
        }
    }
    puts("YES");
    for (register int i=1;i<=n;++i){
        printf("%d ",ans[i]);
    }
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值