我們先挖掘題意,弄清楚題目給的已知條件和要我們輸出什么。
a[l] & a[l+1] & a[l+2] ... & a[r] = q,這是每個(gè)限制的基本形式,由“&”我們可以得知,如若q中的某一個(gè)bit是1的話,則要求a[l]~a[r]中的那個(gè)bit位都為1。這個(gè)條件看似是限制,現(xiàn)在通過轉(zhuǎn)化,似乎可以成為我們的已知條件,即每一個(gè)a[i]中的必須要為1的bit。
通過上述可知,我們得到每個(gè)a[i]的基本值,然后每一個(gè)限制是一個(gè)區(qū)間,很容易就想到了線段樹,對(duì)每一條限制進(jìn)行查詢,看是否沖突,如若沖突則為"NO“,如若不沖突,則就按照a[i]的必須值來輸出即可。
#include#include #define Maxbit 29 #define M_max 123456 #define N_max 123456 #define root 1, 1, n using namespace std; const int noth = (1<<30)-1; int n, m; int l[M_max], r[M_max], q[M_max], a[N_max]; int sum[N_max], tree[N_max*3]; void build(int v, int l, int r) { if (l == r) { tree[v] = a[l]; return; } int ls = v<<1, rs = ls+1, mid = (l+r)>>1; build(ls, l, mid); build(rs, mid+1, r); tree[v] = tree[ls] & tree[rs]; } int query(int v, int l, int r, int ql, int qr) { if (r < ql || l > qr) return noth; if (ql <= l && r <= qr) return tree[v]; int ls = v<<1, rs = ls+1, mid = (l+r)>>1; return query(ls, l, mid, ql, qr) & query(rs, mid+1, r, ql, qr); } void init() { scanf("%d%d", &n, &m); for (int i = 1; i <= m; i++) scanf("%d%d%d", &l[i], &r[i], &q[i]); for (int i = 0; i <= Maxbit; i++) { memset(sum, 0, sizeof(sum)); for (int j = 1; j <= m; j++) if ((q[j] >> i) & 1) { sum[l[j]]++; sum[r[j]+1]--; } for (int j = 1; j <= n; j++) { sum[j] += sum[j-1]; if (sum[j] > 0) a[j] |= 1 << i; } } build(root); } void solve() { for (int i = 1; i <= m; i++) if (query(root, l[i], r[i]) != q[i]) { printf("NO\n"); return; } printf("YES\n"); for (int i = 1; i <= n; i++) printf("%d ", a[i]); printf("\n"); } int main() { init(); solve(); }
聲明:本網(wǎng)頁內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com