zoukankan      html  css  js  c++  java
  • POJ2155/LNSYOJ113 Matrix【二维树状数组+差分】【做题报告】

    这道题是一个二维树状数组,思路十分神奇,其实还是挺水的

    题目描述

    给定一个NNN∗N的矩阵AA,其中矩阵中的元素只有0或者1,其中A[i,j]A[i,j]表示矩阵的第i行和第j列(1i,jN)(1≤i,j≤N),初始矩阵元素都是0。在矩阵上进行TT次操作,操作有以下两种:

    (1)格式为Cx1y1x2y2(1x1x2n,1y1y2n)C x1 y1 x2 y2(1≤x1≤x2≤n,1≤y1≤y2≤n) ,其中CC为字符“C”,表示把以(x1,y1)(x1,y1)为左上角,(x2,y2)(x2,y2)为右下角的这个矩形内的每一个数字同1异或

    (2)格式为Qxy(1x,yn)Q x y(1≤x,y≤n),其中QQ为字符“Q”, 表示询问A[x,y]A[x,y]的值。

    输入格式

    第一行输入XX,表示X组测试数据

    接下来每一组测试数据第一行包含两个整数NN和TT,其中NN表示矩阵的大小,TT表示对矩阵操作次数。

    接下来TT行形式如 "Q x y" or "C x1 y1 x2 y2"操作,见题目中描述

    输出格式

    对于每个QxyQ x y的操作输出答案A[x,y]A[x,y]。

    样例一

    input

    1
    2 10
    C 2 1 2 2
    Q 2 2
    C 2 1 2 1
    Q 1 1
    C 1 1 2 1
    C 1 2 1 2
    C 1 1 2 2
    Q 1 1
    C 1 1 2 1
    Q 2 1
    

    output

    1
    0
    0
    1
    

    限制与约定

    对于30%的数据N100,T3000N≤100,T≤3000

    对于50%的数据N500,T20000N≤500,T≤20000

    对于100%的数据N1000,T50000,X10N≤1000,T≤50000,X≤10

    时间限制1s1s

    空间限制256MB

    首先二维树状数组的标准写法

     1 #define lowbit(a) (a)&(-a)
     2 void change(int px,int py,int val)
     3 {
     4     for(int i=px;i<=n;i+=lowbit(i))
     5         for(int j=py;j<=n;j+=lowbit(j))
     6             tree[i][j]+=val;
     7 }
     8 int ask(int px,int py)
     9 {
    10     int ans=0;
    11     for(int i=px;i;i-=lowbit(i))
    12         for(int j=py;j;j-=lowbit(j))
    13             ans+=tree[i][j];
    14     return ans;
    15 }

    就是一维树状数组加了一层循环,很好理解的233 

    这道题需要打个差分,差分个人理解就是把正常一个数组i与i-1做差,得到的一个差分数组,然后查询时累加前缀和,这么做有很多方便的地方,比如洛谷的树状数组2

    来介绍一下差分

    设数组a[]={1,6,8,5,10},那么差分数组b[]={1,5,2,-3,5}

    也就是说b[i]=a[i]-a[i-1];(a[0]=0;),那么a[i]=b[1]+....+b[i];(这个很好证的)。

    假如区间[2,4]都加上2的话

    a数组变为a[]={1,8,10,7,10},b数组变为b={1,7,2,-3,3};

    发现了没有,b数组只有b[2]和b[5]变了,因为区间[2,4]是同时加上2的,所以在区间内b[i]-b[i-1]是不变的.

    所以对区间[x,y]进行修改,只用修改b[x]与b[y+1]:

    b[x]=b[x]+k;b[y+1]=b[y+1]-k;


    以上就是差分的应用,对于区间修改时应该想到差分,

    比如这道题,就是矩阵的子矩阵修改,这种方法就非常nice

    看下面这张图,修改绿色部分,只需把红色的都+1%2,再累加前缀和能满足(图片出处在水印233)

    其实差分区间修改都可以理解为,比如修改(x,y)全部加2,只要把差分数组中x位置,然后再把y+1减2,就能完美解决,配上树状数组,这样修改和查询就就是O(log(n)),时间复杂度满足

    注意要清数组清数组清数组清数组清数组,没清数组只A了一个点QAQ

    最后放代码

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #define lowbit(a) (a)&(-a)
     5 int t,n,k,x,y,z,w;
     6 int tree[1111][1111];
     7 char opt[5];
     8 void change(int px,int py,int val)
     9 {
    10     for(int i=px;i<=n;i+=lowbit(i))
    11         for(int j=py;j<=n;j+=lowbit(j))
    12             tree[i][j]=(tree[i][j]+val)%2;
    13 }
    14 int ask(int px,int py)
    15 {
    16     int ans=0;
    17     for(int i=px;i;i-=lowbit(i))
    18         for(int j=py;j;j-=lowbit(j))
    19             ans=(ans+tree[i][j])%2;
    20     return ans;
    21 }
    22 int main()
    23 {
    24     scanf("%d",&t);
    25     while(t--)
    26     {
    27         memset(tree,0,sizeof(tree));
    28         scanf("%d%d",&n,&k);
    29         for(int i=1;i<=k;i++)
    30         {
    31             scanf("%s",opt);
    32             if(opt[0]=='C')
    33             {
    34                 scanf("%d%d%d%d",&x,&y,&z,&w);
    35                 change(x,y,1),change(z+1,w+1,1),change(x,w+1,1),change(z+1,y,1);
    36             }else if(opt[0]=='Q')
    37             {
    38                 scanf("%d%d",&x,&y);
    39                 printf("%d
    ",ask(x,y));
    40             }
    41         }
    42     }
    43     return 0;
    44 }

     

    By  浅夜_MISAKI

    转载于:https://www.cnblogs.com/Qin-Wei-Kai/p/10052168.html

  • 相关阅读:
    LeetCode 258 Add Digits
    LeetCode 231 Power of Two
    LeetCode 28 Implement strStr()
    LeetCode 26 Remove Duplicates from Sorted Array
    LeetCode 21 Merge Two Sorted Lists
    LeetCode 20 Valid Parentheses
    图形处理函数库 ImageTTFBBox
    php一些函数
    func_get_arg(),func_get_args()和func_num_args()的用法
    人生不是故事,人生是世故,摸爬滚打才不会辜负功名尘土
  • 原文地址:https://www.cnblogs.com/twodog/p/12135522.html
Copyright © 2011-2022 走看看