1. 程式人生 > 實用技巧 >#線段樹#A 或位運算

#線段樹#A 或位運算

題目

一個長度為\(n\)的非負整數序列,
需要滿足\(m\)個區間或值為閾值的限制條件
現在要構造一個這樣的序列,不存在輸出No


分析

線段樹支援區間與,但查詢區間或,下傳標記,那就很好做了


程式碼

#include <cstdio>
#include <cctype>
#define rr register
using namespace std;
const int inf = (1 << 30) - 1, N = 100011;
int a[N], w[N << 2], lazy[N << 2], n, m, l[N], r[N], z[N];
inline signed iut() {
    rr int ans = 0;
    rr char c = getchar();
    while (!isdigit(c)) c = getchar();
    while (isdigit(c)) ans = (ans << 3) + (ans << 1) + (c ^ 48), c = getchar();
    return ans;
}
inline void print(int ans) {
    if (ans > 9)
        print(ans / 10);
    putchar(ans % 10 + 48);
}
inline void build(int k, int l, int r) {
    w[k] = lazy[k] = inf;
    if (l == r)
        return;
    rr int mid = (l + r) >> 1;
    build(k << 1, l, mid);
    build(k << 1 | 1, mid + 1, r);
}
inline void pdown(int k) {
    w[k << 1] &= lazy[k], w[k << 1 | 1] &= lazy[k], lazy[k << 1] &= lazy[k], lazy[k << 1 | 1] &= lazy[k],
        lazy[k] = inf;
}
inline void update(int k, int l, int r, int x, int y, int z) {
    if (l == x && r == y) {
        w[k] &= z, lazy[k] &= z;
        return;
    }
    rr int mid = (l + r) >> 1;
    if (lazy[k] ^ inf)
        pdown(k);
    if (y <= mid)
        update(k << 1, l, mid, x, y, z);
    else if (x > mid)
        update(k << 1 | 1, mid + 1, r, x, y, z);
    else
        update(k << 1, l, mid, x, mid, z), update(k << 1 | 1, mid + 1, r, mid + 1, y, z);
    w[k] = w[k << 1] | w[k << 1 | 1];
}
inline signed query(int k, int l, int r, int x, int y) {
    if (l == x && r == y)
        return w[k];
    rr int mid = (l + r) >> 1;
    if (lazy[k] ^ inf)
        pdown(k);
    if (y <= mid)
        return query(k << 1, l, mid, x, y);
    else if (x > mid)
        return query(k << 1 | 1, mid + 1, r, x, y);
    else
        return query(k << 1, l, mid, x, mid) | query(k << 1 | 1, mid + 1, r, mid + 1, y);
}
inline void dfs(int k, int l, int r) {
    if (l == r) {
        a[l] = w[k];
        return;
    };
    rr int mid = (l + r) >> 1;
    if (lazy[k] ^ inf)
        pdown(k);
    dfs(k << 1, l, mid);
    dfs(k << 1 | 1, mid + 1, r);
    w[k] = w[k << 1] | w[k << 1 | 1];
}
signed main() {
    freopen("or.in", "r", stdin);
    freopen("or.out", "w", stdout);
    n = iut(), m = iut(), build(1, 1, n);
    for (rr int i = 1; i <= m; ++i) {
        l[i] = iut(), r[i] = iut(), z[i] = iut();
        update(1, 1, n, l[i], r[i], z[i]);
    }
    for (rr int i = 1; i <= m; ++i)
        if (query(1, 1, n, l[i], r[i]) < z[i])
            return !printf("No");
    dfs(1, 1, n), printf("Yes");
    for (rr int i = 1; i <= n; ++i) putchar(i == 1 ? 10 : 32), print(a[i]);
    return 0;
}