Codeforces Round #275 (Div. 2) D

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;
}


你可能感兴趣的:(线段树)