D. Interesting Array
题意:一个长度为n的序列,有m个要求,对于每个要求给出li,ri,qi,意味着序列中从li到ri这个区间内的所有值与运算后得到qi,问这样的序列是否存在,如果存在,输出任意可行序列。
思路:线段树(区间更新)。节点存的是相应区间内所有数“与”起来的值,对每个要求mi,为对应区间“或”上qi,最后再对每个要求查询一次,看是否满足。
#include<cstdio> #include<iostream> #include<algorithm> #include<string.h> #include<math.h> using namespace std; #define maxn 100010 #define ll long long struct node{ ll val,add; int l,r; }; node tree[maxn<<2]; void build_tree(int n,int l,int r){ tree[n].l=l; tree[n].r=r; tree[n].val=tree[n].add=0LL; if(l==r)return; int mid=(l+r)>>1; build_tree(n<<1,l,mid); build_tree((n<<1)|1,mid+1,r); } void push_down(int x){ tree[x<<1].val|=tree[x].add; tree[(x<<1)|1].val|=tree[x].add; tree[x<<1].add|=tree[x].add; tree[(x<<1)|1].add|=tree[x].add; tree[x].add=0LL; } void push_up(int x){ tree[x].val=tree[x<<1].val&tree[(x<<1)|1].val; } void update(int n,int l,int r,ll v){ if(tree[n].l==l&&tree[n].r==r){ tree[n].val|=v; tree[n].add|=v; return; } if(tree[n].add)push_down(n); int mid=(tree[n].l+tree[n].r)>>1; if(r<=mid){ update(n<<1,l,r,v); }else{ if(l>mid){ update((n<<1)|1,l,r,v); }else{ update(n<<1,l,mid,v); update((n<<1)|1,mid+1,r,v); } } push_up(n); } ll query(int n,int l,int r){ if(tree[n].l==l&&tree[n].r==r){ return tree[n].val; } if(tree[n].add)push_down(n); int mid=(tree[n].l+tree[n].r)>>1; if(r<=mid){ return query(n<<1,l,r); }else{ if(l>mid){ return query((n<<1)|1,l,r); }else{ return query(n<<1,l,mid)&query((n<<1)|1,mid+1,r); } } } int ql[maxn]; int qr[maxn]; ll qq[maxn]; int main(){ int n,m; while(cin>>n>>m){ build_tree(1,1,n); for(int i=1;i<=m;i++){ scanf("%d%d%I64d",&ql[i],&qr[i],&qq[i]); update(1,ql[i],qr[i],qq[i]); } bool ok=1; for(int i=1;i<=m;i++){ if(query(1,ql[i],qr[i])!=qq[i]){ ok=0;break; } } if(ok){ printf("YES\n"); for(int i=1;i<=n;i++){ printf("%I64d ",query(1,i,i)); } }else{ printf("NO\n"); } } return 0; }