Codeforces Round #275 (Div. 2) D题 (线段树)

D. Interesting Array
time limit per test
1 second
memory limit per test
256 megabytes

We'll call an array of n non-negative integersa[1], a[2], ..., a[n]interesting, if it meets m constraints. The i-th of them constraints consists of three integersli,ri,qi (1 ≤ li ≤ ri ≤ n) meaning that value should be equal toqi.

Your task is to find any interesting array of n elements or state that such array doesn't exist.

Expression x&y means the bitwise AND of numbersx andy. In programming languages C++, Java and Python this operation is represented as "&", in Pascal — as "and".

Input

The first line contains two integers n, m (1 ≤ n ≤ 105,1 ≤ m ≤ 105) — the number of elements in the array and the number of limits.

Each of the next m lines contains three integersli,ri,qi (1 ≤ li ≤ ri ≤ n,0 ≤ qi < 230) describing thei-th limit.

Output

If the interesting array exists, in the first line print "YES" (without the quotes) and in the second line printn integersa[1], a[2], ..., a[n] (0 ≤ a[i] < 230) decribing theinteresting array. If there are multiple answers, print any of them.

If the interesting array doesn't exist, print "NO" (without the quotes) in the single line.

Sample test(s)
Input
3 1
1 3 3
Output
YES
3 3 3
Input
3 2
1 3 3
1 3 2
Output
NO


题目链接 :http://codeforces.com/contest/483/problem/D


题目大意 :输入n个数的序列,有m组(m个限制),要求求一组序列满足该序列的l位置到r位置的值的与等于q,若不存在输出No


题目分析 :线段树维护,判a[l]&a[l+1]&...&a[r]的值是否等于q,要满足这样的条件,我们可以用q去和每个节点取或运算,因为每个节点在一起的与值是固定的等于q 比如 q = 3 = 111(2),节点初始化为0要满足上述条件,则要用111 | 000得到每个节点的值,算出来为111(2) = 3.


#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
int const MAX = 110000;
struct Node
{
    int l, r;
    int val;
};
Node tree[10 * MAX];
Node a[MAX];
vector<int> ans;

void build(int step, int l, int r)
{
    tree[step].l = l;
    tree[step].r = r;
    tree[step].val = 0;
    if(l == r)
        return;
    int mid = (l + r) >> 1;
    build(step << 1, l, mid);
    build(((step << 1) + 1), mid+1, r);
}

void update(int step, int l, int r, int val)
{
    if(tree[step].l == l && tree[step].r == r)
    {
        tree[step].val |= val;
        return;
    }
    int mid = (tree[step].l + tree[step].r) >> 1;
    if(r <= mid)
        update(step << 1, l, r, val);
    else if(l > mid)
        update((step << 1) + 1, l, r, val);
    else
    {
        update(step << 1, l, mid, val);
        update((step << 1) + 1, mid+1, r, val);
    }
}

int query(int step, int l, int r)
{
    if(tree[step].l == l && tree[step].r == r)
        return tree[step].val;
    int mid = (tree[step].l + tree[step].r) >> 1;
    if(r <= mid)
        return query(step << 1, l, r);
    if(l > mid)
        return query((step << 1) + 1, l, r);
    else
        return query(step << 1, l, mid) & query((step << 1) + 1, mid+1, r);
}

void solve(int step)
{
    if(step != 1)
        tree[step].val |= tree[step >> 1].val;
    if(tree[step].l == tree[step].r)
    {
        ans.push_back(tree[step].val);
        return;
    }
    solve(step << 1);
    solve((step << 1) + 1);
}

int main()
{
    int n, m;
    scanf("%d %d", &n, &m);
    build(1, 1, n);
    for(int i = 0; i < m; i++)
    {
        scanf("%d %d %d", &a[i].l, &a[i].r, &a[i].val);
        update(1, a[i].l, a[i].r, a[i].val);
    }
    bool flag = true;
    for(int i = 0; i < m; i++)
    {
        if(query(1, a[i].l, a[i].r) != a[i].val)
        {
            flag = false;
            break;
        }
    }
    if(flag)
    {
        solve(1);
        printf("YES\n");
        for(int i = 0; i < ans.size(); i++)
            printf("%d%c",ans[i], i == n ? '\n' : ' ');
        ans.clear();
        printf("\n");
    }
    else
        printf("NO\n");
}



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