Magic Board (codechef February 2013 Challenge)

题目链接 : http://acm.bnu.edu.cn/v3/problem_show.php?pid=40517

这又是很不错的一道题目。

题意是给一个n*n(n <= 1e5)的矩阵,初始都为0,然后m(<=1e5)次操作,每次可以把一行或者一列全部标记为0或者1,或者询问某一行或者某一列有多少个0.

做法很巧妙,考虑到我如果查询第x行,那么的话我先找到前一次对x行操作的的时间点time_x,这样的话在time_x之前的所有操作对于x行都是无影响的,然后现在对于x行有影响的就只有在时间点time_x+1 到上一次操作所有对列的置1操作数或者置0操作数,这里假如先对y列进行了置1,后来又对y进行置0或者1操作的话需要把前一次操作的影响给去掉的,这样我们可以对于时间开一棵线段树/BIT,区间查询和单点修改就行了。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 
 5 using namespace std;
 6 #define lson a, rt<<1, l, mid
 7 #define rson a, rt<<1|1, mid+1, r
 8 const int MAXN = 500005;
 9 int O[2][MAXN<<2] = {0}, I[2][MAXN<<2] = {0};
10 int ord[2][MAXN];
11 int pre[2][MAXN];
12 int n, m;
13 
14 void Up(int a[], int rt) {
15     a[rt] = a[rt<<1] + a[rt<<1|1];
16 }
17 int query(int a[], int rt, int l, int r, int L, int R) {
18     if (l >= L && r <= R) {
19         return a[rt];
20     }
21     int mid = r + l >> 1, ret = 0;
22     if (mid >= L) ret += query(lson, L, R);
23     if (R > mid) ret += query(rson, L, R);
24     return ret;
25 }
26 void update(int a[], int rt, int l, int r, int p, int c) {
27     if (l == r) {
28         a[rt] = c;
29         return ;
30     }
31     int mid = r + l >> 1;
32     if (mid >= p) update(lson, p, c);
33     else update(rson, p, c);
34     Up(a, rt);
35     return ;
36 }
37 void init() {
38     for (int i = 1; i <= n; i++) pre[0][i] = pre[1][i] = 0;
39     for (int i = 1; i <= n; i++) ord[0][i] = ord[1][i] = 0;
40 }
41 
42 int main() {
43     scanf("%d%d", &n, &m);
44     init();
45     for (int q = 1; q <= m; q ++) {
46         char op[11];
47         int d, x, y, ret;
48         scanf("%s", op);
49         d = (op[0] == 'R');
50         if (op[3] == 'Q') {
51             scanf("%d", &x);
52             if (ord[d][x] == 1) {
53                 ret = query(O[d^1], 1, 1, m, pre[d][x]+1, q);
54             }else {
55                 ret = n - query(I[d^1], 1, 1, m, pre[d][x]+1, q);
56             }
57             printf("%d
", ret);
58         }else {
59             scanf("%d%d", &x, &y);
60             update(y == 1 ? I[d] : O[d], 1, 1, m, q, 1);
61             if (ord[d][x] == 0) {
62                 if (pre[d][x] >= 1)update(O[d], 1, 1, m, pre[d][x], 0);
63             }else {
64                 if (pre[d][x] >= 1)update(I[d], 1, 1, m, pre[d][x], 0);
65             }
66             ord[d][x] = y; pre[d][x] = q;
67         }
68     }
69     return 0;
70 }
View Code
原文地址:https://www.cnblogs.com/danceonly/p/4029833.html