zoukankan      html  css  js  c++  java
  • POJ 2155 Matrix (树状数组 && 区间计数)

    题意 : 给出一个N*N的矩阵, 矩阵只有可能包含0或1, 一开始则全部是0。对于矩阵可以进行两种操作, 第一种是输入 C x1 y1 x2 y2 表示, 对以(x1, y1)为左上角, 以(x2, y2)为右下角构成的矩形区域内的数全部进行取反操作, 即0变1、1变0。第二种是Q X Y, 表示查询现在这个矩阵的(X, Y)点到底是0还是1。总共有T次操作, 对于C操作进行相应的修改, 对于Q操作要对应输出!

    分析 : 据说是楼教主出的题, 自己确实想不出什么高效的办法, 参考网上的题解, 才得知解题思想源自一篇国家队论文, 说简单一点就是对于题目要求的C操作, 实际上只要更新这个小矩形区域的四个点即可, 也就是不必全部照样更新。在Q操作查询时候也只要进行二维的树状数组进行(1,1)到(X, Y)点的矩形区域求和, 然后将求和结果%2, 如果得1即这个点被进行了奇数次操作, 所以应为1, 得0则反之。至于为什么或者如何做, 论文讲的很清楚, 请百度: 《浅谈信息学竞赛中的“0”和“1”

    瞎想 : 很值得借鉴的是对于是否是0或1的判断, 被转化成判断了对这个点操作次数的奇偶。还有对于区间的修改, 对于一维只进行两点的起始标记, 二维则进行四个点的起始标记, 这个也是厉害!

    #include<stdio.h>
    #include<string.h>
    #define lowbit(i) (i&(-i))
    const int maxn = 1001;
    int c[maxn][maxn], n;
    inline void add(int row, int col)
    {
        for(int i=row; i<=n; i+=lowbit(i)){
            for(int j=col; j<=n; j+=lowbit(j)){
                c[i][j]++;
            }
        }
    }
    int sum(int row, int col)
    {
        int ans = 0;
        for(int i=row; i>0; i-=lowbit(i)){
            for(int j=col; j>0; j-=lowbit(j)){
                ans += c[i][j];
            }
        }
        return ans;
    }
    inline void initialize(int k)
    {
        for(int i=0; i<=k; i++){
            memset(c[i], 0, sizeof(c[i]));
        }
    }
    int main(void)
    {
        int nCase;
        scanf("%d", &nCase);
        while(nCase--){
            scanf("%d", &n);
            initialize(n);
            int num;
            scanf("%d", &num);
            while(num--){
                char command;
                scanf(" %c", &command);
                if(command=='C'){
                    int x1, y1, x2, y2;
                    scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
                    add(x1, y1);
                    add(x2+1, y1);
                    add(x1, y2+1);
                    add(x2+1, y2+1);
                }else{
                    int x, y;
                    scanf("%d%d", &x, &y);
                    int SUM = sum(x, y);
                    printf("%d
    ", SUM&1);//&1和%2好像效率一样!
                }
            }
            puts("");//注意这里, 用例之间要空个行, 避免PE
        }
        return 0;
    }
    View Code
  • 相关阅读:
    POJ1769 Minimizing maximizer(DP + 线段树)
    ZOJ3201 Tree of Tree(树形DP)
    POJ3613 Cow Relays(矩阵快速幂)
    POJ3635 Full Tank?(DP + Dijkstra)
    ZOJ3195 Design the city(LCA)
    POJ3368 Frequent values(RMQ线段树)
    POJ3686 The Windy's(最小费用最大流)
    HDU4871 Shortest-path tree(最短路径树 + 树的点分治)
    POJ3013 Big Christmas Tree(最短路径树)
    Gym100685G Gadget Hackwrench(倍增LCA)
  • 原文地址:https://www.cnblogs.com/qwertiLH/p/6919929.html
Copyright © 2011-2022 走看看