1. 程式人生 > >【CodeChef】Xor Table

【CodeChef】Xor Table

【題目連結】

【思路要點】

  • 我們可以將 c i , j
    c_{i,j}
    看做二分圖的邊集,找到圖中每一個聯通塊,確定其中一個數便可以確定所有數,因此,問題等價於我們需要求解滿足若干不等式 l x v
    a l r l≤x\oplus val≤r
    x
    x
    的一組解或指出其無解。
  • 直接從高位向低位搜尋即可,這部分的複雜度筆者尚不是很明確,可以肯定的是,它不會超過 O ( ( N + M ) 2 L o g V ) O((N+M)^2LogV) ,但從實際執行的效率來看,它似乎有著更好的複雜度。
  • 時間複雜度 O ( N M + ( N + M ) 2 L o g V ) O(NM+(N+M)^2LogV)

【程式碼】

#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;
}