noip模拟赛 fateice-or

 

分析:or操作只有在结果的这一位为0的情况下才会强制要求两个数的这一位都为0,其它时候不强求,所以为了最大限度地满足条件,我们先把所有的数的所有位全部变成1,如果p的第i位为0,那么[l,r]的数的第i位都要为0,&一下p就好了.最后检验一下看看是否满足所有条件就可以了。为什么这样做事合法的呢?因为我们之前已经尽可能让它最大限度地满足条件了,某一位更改后可能就不能满足这么多条件了,如果这都不行,那么肯定无解.因为是区间&操作,所以用线段树来优化.

构造题要满足所有的条件,那么就构造出尽可能多地满足条件的,最后检验一下就可以了.

    注意:实际操作是|,但是每次进行的操作是&,在合并和修改的时候不要弄混了.

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int inf = (1 << 30) - 1, maxn = 300010;

int n, m, l[maxn], r[maxn], p[maxn], v[maxn * 4], tag[maxn * 4], flag[maxn * 4];
bool can = true;

void build(int o, int l, int r)
{
    tag[o] = v[o] = inf;
    if (l == r)
        return;
    int mid = (l + r) >> 1;
    build(o * 2, l, mid);
    build(o * 2 + 1, mid + 1, r);
}

void pushup(int o)
{
    v[o] = v[o * 2] | v[o * 2 + 1];
}

void pushdown(int o)
{
    if (flag[o])
    {
        flag[o * 2] = flag[o * 2 + 1] = 1;
        flag[o] = 0;
        tag[o * 2] &= tag[o];
        tag[o * 2 + 1] &= tag[o];
        v[o * 2] &= tag[o];
        v[o * 2 + 1] &= tag[o];
        tag[o] = inf;
    }
}

void update(int o, int l, int r, int x, int y, int c)
{
    if (x <= l && r <= y)
    {
        tag[o] &= c;
        v[o] &= c;
        flag[o] = 1;
        return;
    }
    pushdown(o);
    int mid = (l + r) >> 1;
    if (x <= mid)
        update(o * 2, l, mid, x, y, c); 
    if (y > mid)
        update(o * 2 + 1, mid + 1, r, x, y, c);
    pushup(o);
}

int query(int o, int l, int r, int x, int y)
{
    if (x <= l && r <= y)
        return v[o];
    pushdown(o);
    int mid = (l + r) >> 1, res = 0;
    if (x <= mid)
        res |= query(o * 2, l, mid, x, y); 
    if (y > mid)
        res |= query(o * 2 + 1, mid + 1, r, x, y);
    return res;
}

int main()
{
    freopen("or1.in", "r", stdin);
    freopen("or2.txt", "w", stdout);
    scanf("%d%d", &n, &m);
    build(1, 1, n);
    for (int i = 1; i <= m; i++)
    {
        scanf("%d%d%d", &l[i], &r[i], &p[i]);
        update(1, 1, n, l[i], r[i], p[i]);
    }
    for (int i = 1; i <= m; i++)
        if (query(1, 1, n, l[i], r[i]) != p[i])
        {
            can = 0;
            break;
        }
    if (can == false)
        printf("No\n");
    else
    {
        printf("Yes\n");
        for (int i = 1; i <= n; i++)
            printf("%d ",query(1,1,n,i,i));
    }

    return 0;
}

 

posted @ 2017-10-15 21:43  zbtrs  阅读(775)  评论(0编辑  收藏  举报