CodeForces 482 B.Interesting Array (线段树)

题意:

给n和m
和m个l,r,x
要求构造一个数组,使得对于m个条件l,r,x
[l,r]的区间与(&)结果为x

思路:

对于每个l,r,x
如果x的某一位为1,则[l,r]中每一位的这个位置都要为1
所以直接对区间[l,r]的这一位赋值为1

m次操作结束之后再对m个操作判断区间[l,r]的区间与是否等于x就行了
如果不等于则说明条件中有互相冲突的,则无解

区间操作用线段树实现

code:
#include<bits/stdc++.h>
using namespace std;
const int maxm=1e5+5;
int a[maxm<<2];
int laz[maxm<<2];
struct Q{
    int l,r,x;
}q[maxm];
void pushdown(int node){
    if(laz[node]){
        int lz=laz[node];
        a[node*2]|=lz;
        a[node*2+1]|=lz;
        laz[node*2]|=lz;
        laz[node*2+1]|=lz;
        laz[node]=0;
    }
}
void pushup(int node){
    a[node]=(a[node*2]&a[node*2+1]);
}
void update(int st,int ed,int val,int l,int r,int node){
    if(st<=l&&ed>=r){
        a[node]|=val;
        laz[node]|=val;
        return ;
    }
    pushdown(node);
    int mid=(l+r)/2;
    if(st<=mid){
        update(st,ed,val,l,mid,node*2);
    }
    if(ed>=mid+1){
        update(st,ed,val,mid+1,r,node*2+1);
    }
    pushup(node);
}
int ask(int st,int ed,int l,int r,int node){
    if(st<=l&&ed>=r){
        return a[node];
    }
    pushdown(node);
    int mid=(l+r)/2;
    int ans=(1<<30)-1;//全1
    if(st<=mid){
        ans&=ask(st,ed,l,mid,node*2);
    }
    if(ed>=mid+1){
        ans&=ask(st,ed,mid+1,r,node*2+1);
    }
    pushup(node);
    return ans;
}
signed main(){
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        int l,r,x;
        cin>>l>>r>>x;
        update(l,r,x,1,n,1);
        q[i]={l,r,x};
    }
    for(int i=1;i<=m;i++){
        int l=q[i].l,r=q[i].r;
        int x=q[i].x;
        if(ask(l,r,1,n,1)!=x){//如果不满足直接no
            cout<<"NO"<<endl;
            return 0;
        }
    }
    cout<<"YES"<<endl;
    for(int i=1;i<=n;i++){//输出每一个
        cout<<ask(i,i,1,n,1)<<' ';
    }
    cout<<endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值