HDU-水饺基情 二维树状数组
该题就是简单的二维树状数组,保留一份棋盘的最新状态即可,树状数组里面就只保留在原有基础上增加或者减少的某一种饺子的数量。
代码如下:
#include <cstring> #include <cstdlib> #include <cstdio> using namespace std; char op[5]; char G[1050][1050]; int cc[1050][1050]; // 数组中存储韭菜饺的数量,白菜饺的数量通过总数量减去韭菜饺来求 void init() { int k = 0; // 定义韭菜为1,白菜为0 for (int i = 1; i <= 1024; ++i) { for (int j = 1; j <= 1025; ++j) { // 由于一行的结束和另一行的开始种类相同,所以多加了一列来翻转k G[i][j] = (k ^= 1); } } } int lowbit(int x) { return x & -x; } void modify(int x, int y, int val) { for (int i = x; i <= 1024; i += lowbit(i)) { for (int j = y; j <= 1024; j += lowbit(j)) { cc[i][j] += val; } } } int sum(int x, int y) { int tot = 0; for (int i = x; i > 0; i -= lowbit(i)) { for (int j = y; j > 0; j -= lowbit(j)) { tot += cc[i][j]; } } return tot; } int main() { int T, a, b, c, d, k; int A, B, C, S; while (scanf("%d", &T) == 1) { init(); memset(cc, 0, sizeof (cc)); while (T--) { scanf("%s", op); if (op[0] == 'R') { scanf("%d %d %d %d", &a, &b, &c, &d); A = sum(c, d) - sum(c, b-1) - sum(a-1, d) + sum(a-1, b-1); if ((a + b) & 1) { // 白菜多数 S = (c-a+1)*(d-b+1) / 2; } else { S = ((c-a+1)*(d-b+1) + 1)/ 2; } B = S + A; C = (c-a+1)*(d-b+1) - B; printf("%d %d\n", B, C); } else { // 'A' 为韭菜,‘B’ 为白菜 scanf("%d %d", &a, &b); k = op[0] == 'A'; // 1为韭菜,0为白菜 if (k != G[a][b]) { G[a][b] = k; if (k) { modify(a, b, 1); } else { modify(a, b, -1); } } } } } return 0; }