【CodeChef】Xor Table
阿新 • • 發佈:2018-12-13
【題目連結】
【思路要點】
- 我們可以將 看做二分圖的邊集,找到圖中每一個聯通塊,確定其中一個數便可以確定所有數,因此,問題等價於我們需要求解滿足若干不等式 的 的一組解或指出其無解。
- 直接從高位向低位搜尋即可,這部分的複雜度筆者尚不是很明確,可以肯定的是,它不會超過 ,但從實際執行的效率來看,它似乎有著更好的複雜度。
- 時間複雜度 。
【程式碼】
#include<bits/stdc++.h> using namespace std; const int MAXN = 1005; const int MAXM = 1e6 + 5; typedef long long ll; typedef long double ld; typedef unsigned long long ull; template <typename T> void chkmax(T &x, T y) {x = max(x, y); } template <typename T> void chkmin(T &x, T y) {x = min(x, y); } template <typename T> void read(T &x) { x = 0; int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; x *= f; } template <typename T> void write(T x) { if (x < 0) x = -x, putchar('-'); if (x > 9) write(x / 10); putchar(x % 10 + '0'); } template <typename T> void writeln(T x) { write(x); puts(""); } int n, m, cnt, al[MAXN], ar[MAXN], bl[MAXN], br[MAXN]; int x[MAXM], l[MAXM], r[MAXM], a[MAXN], b[MAXN], c[MAXN][MAXN]; bool visa[MAXN], visb[MAXN]; int getans(int pos, int sum, int pre) { int bit = 1 << (pos + 1) >> 1, delta; if (bit == 0) delta = 0; else delta = bit * 2 - 1; for (int i = 1; i <= cnt; i++) if (max(l[i], sum ^ (pre & x[i])) > min(r[i], (sum ^ (pre & x[i])) + delta)) { return -1; } if (pos == -1) return sum; int ans = -1; ans = getans(pos - 1, sum, pre + bit); if (ans != -1) return ans; ans = getans(pos - 1, sum + bit, pre + bit); return ans; } void work(int pos, int type, int sum) { if (!type) { visa[pos] = true; x[++cnt] = sum; l[cnt] = al[pos]; r[cnt] = ar[pos]; for (int i = 1; i <= m; i++) if (!visb[i] && c[pos][i] != -1) work(i, !type, sum ^ c[pos][i]); } else { visb[pos] = true; x[++cnt] = sum; l[cnt] = bl[pos]; r[cnt] = br[pos]; for (int i = 1; i <= n; i++) if (!visa[i] && c[i][pos] != -1) work(i, !type, sum ^ c[i][pos]); } } void attach(int pos, int type, int sum) { if (!type) { a[pos] = sum; for (int i = 1; i <= m; i++) if (visb[i] && b[i] == -1 && c[pos][i] != -1) attach(i, !type, sum ^ c[pos][i]); } else { b[pos] = sum; for (int i = 1; i <= n; i++) if (visa[i] && a[i] == -1 && c[i][pos] != -1) attach(i, !type, sum ^ c[i][pos]); } } int main() { int T; read(T); while (T--) { read(n), read(m); for (int i = 1; i <= n; i++) read(al[i]), read(ar[i]), a[i] = -1; for (int i = 1; i <= m; i++) read(bl[i]), read(br[i]), b[i] = -1; for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) read(c[i][j]); memset(visa, false, sizeof(visa)); memset(visb, false, sizeof(visb)); bool failed = false; for (int i = 1; i <= n && !failed; i++) if (!visa[i]) { cnt = 0, work(i, 0, 0); int tmp = getans(29, 0, 0); failed |= tmp == -1; if (tmp != -1) attach(i, 0, tmp); } for (int i = 1; i <= m && !failed; i++) if (!visb[i]) { cnt = 0, work(i, 1, 0); int tmp = getans(29, 0, 0); failed |= tmp == -1; if (tmp != -1) attach(i, 1, tmp); } for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) if (c[i][j] != -1 && (a[i] ^ b[j]) != c[i][j]) failed = true; if (failed) puts("NO"); else { puts("YES"); for (int i = 1; i <= n; i++) printf("%d ", a[i]); printf("\n"); for (int i = 1; i <= m; i++) printf("%d ", b[i]); printf("\n"); } } return 0; }