CodeForces 1864D Matrix Cascade

发布时间 2023-08-29 07:56:05作者: zltzlt

洛谷传送门

CF 传送门

拆题中式子的绝对值,得:

  • \(x - y \ge i - j\)
  • \(x + y \ge i + j\)

也就是说我们操作 \((i, j)\) 会影响到满足上面条件的所有点 \((x, y)\)

考虑按 \(i + j\) 从小到大操作,这样第二个条件就可以舍去。那我们只需要一个树状数组维护有多少个已操作的点满足第一个条件,就可以知道 \((x, y)\) 的状态,从而知道该点是否需要操作。

时间复杂度 \(O(n^2 \log n)\)

code
// Problem: D. Matrix Cascade
// Contest: Codeforces - Harbour.Space Scholarship Contest 2023-2024 (Div. 1 + Div. 2)
// URL: https://codeforces.com/contest/1864/problem/D
// Memory Limit: 512 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
#define pb emplace_back
#define fst first
#define scd second
#define mkp make_pair
#define mems(a, x) memset((a), (x), sizeof(a))

using namespace std;
typedef long long ll;
typedef double db;
typedef unsigned long long ull;
typedef long double ldb;
typedef pair<ll, ll> pii;

const int maxn = 3030;

int n;
char s[maxn][maxn];

namespace BIT {
	int c[maxn * 2];
	
	inline void init() {
		for (int i = 1; i <= n * 2; ++i) {
			c[i] = 0;
		}
	}
	
	inline void update(int x, int d) {
		for (int i = x; i <= n * 2; i += (i & (-i))) {
			c[i] += d;
		}
	}
	
	inline int query(int x) {
		int res = 0;
		for (int i = x; i; i -= (i & (-i))) {
			res += c[i];
		}
		return res;
	}
}

void solve() {
	BIT::init();
	scanf("%d", &n);
	for (int i = 1; i <= n; ++i) {
		scanf("%s", s[i] + 1);
	}
	int ans = 0;
	for (int p = 2; p <= n * 2; ++p) {
		for (int i = 1; i < p && i <= n; ++i) {
			int j = p - i;
			if (j > n) {
				continue;
			}
			int k = s[i][j] - '0';
			k += BIT::query(i - j + n);
			if (k & 1) {
				++ans;
				BIT::update(i - j + n, 1);
			}
		}
	}
	printf("%d\n", ans);
}

int main() {
	int T = 1;
	scanf("%d", &T);
	while (T--) {
		solve();
	}
	return 0;
}