CODEFORCES, 483D Interesting Array

来源:互联网 发布:网站数据库上传 编辑:程序博客网 时间:2024/04/29 07:48

题意:有一个长度为n的数组a,有m个要求,其中每个要求l,r,q代表 从a[l]&a[l+1]&....&a[r-1]&a[r]=q

问满足这一的数组a是否存在,若存在输出任意满足条件的即可。

nm (1 ≤ n ≤ 1051 ≤ m ≤ 105)

策略:很显然的会想到线段树,对于每一个查询我们将q和区间值进行或操作,这样就不会改变应有性质,但是问题在于可能有操作会将某些要求的整个区间的q 改为其他值。即该区间的&结果会改变。所以我们在最后需要检查这样的一系列操作后仍否满足各个条件。

首先对于每一个区间的或操作我们都会有logn的复杂度 即总复杂度为mlogn

之后我们再检查每一个区间的&结果,这里我们仍然需要成段查询,不然会超时。

所以我们要做一次操作,把树上所有或的结果变成与的结果。我们可以从树根到叶子遍历一次将遇到的所有的值或,更新到叶节点,得到每个数的值,非叶子节点我们再返回节点左右的儿子的与值,这样我们就得到了每一个区间的&值。这样对树上的每一个节点都遍历了一边 复杂度应该在O (10^5)级 即O(n)

然后对于每一次检查 我们的复杂度就可以保证每次在logn级别,总复杂度也就在mlogn

所以总复杂度为 mlogn+n 满足要求。


//Author:Wenjun Shi//on 2016/7/14#include <iostream>#include <cstdio>#include <climits>#define MAX_N 200005using namespace std;int sg_tree[MAX_N*2];int ans[MAX_N];void update(int lt,int rt,int l,int r,int i,int val){    if(lt>r||rt<l) return ;    if(lt<=l&&rt>=r) {sg_tree[i]|=val;return;}  //  sg_tree[i]|=val;  //  if(l==r) return;    int mid=(l+r)/2;    update(lt,rt,l,mid,i+i,val);    update(lt,rt,mid+1,r,i+i+1,val);}void plant(int i,int l,int r,int val=0){    val|=sg_tree[i];    if(l==r)    {        sg_tree[i]=val;        ans[l]=val;        return ;    }    int mid=(l+r)/2;    plant(i+i,l,mid,val);    plant(i+i+1,mid+1,r,val);    sg_tree[i]=sg_tree[i+i]&sg_tree[i+i+1];}int check(int lt,int rt,int l,int r,int i){    if(lt>r||rt<l) return -1;    if(lt<=l&&rt>=r)    {        return sg_tree[i];    }    int mid=(l+r)/2;    int v1=check(lt,rt,l,mid,i+i);    int v2=check(lt,rt,mid+1,r,i+i+1);    if(v1==-1) return v2;    if(v2==-1) return v1;    return v1&v2;}int n,m,l[MAX_N],r[MAX_N],q[MAX_N];int main(){    scanf("%d%d",&n,&m);   // build_tree(1,n,1);    bool ok=1;    for(int i=0; i<m; i++)    {        scanf("%d%d%d",&l[i],&r[i],&q[i]);        update(l[i],r[i],1,n,1,q[i]);    }    plant(1,1,n);    for(int i=0; i<m; i++)    {        if(check(l[i],r[i],1,n,1)!=q[i]){            ok=0;        break;        }    }    if(!ok) cout<<"NO"<<endl;    else    {        cout<<"YES"<<endl;        for(int i=1; i<=n; i++)        {            printf("%d ",ans[i]);        }        cout<<endl;    }    return 0;}


0 0
原创粉丝点击