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

  • 相关阅读:
    第二篇第十一章灭火救援设施
    第二篇第六章安全疏散
    第二篇第五章防火防烟分区于分隔
    第二篇第三章建筑分类与耐火等级
    applicationContext-solr.xml
    solrj 操作 solr 集群版
    centos solr 集群搭建
    org.apache.ibatis.binding.BindingException
    全文检索基础
    solrj 操作 solr 单机版
  • 原文地址:https://www.cnblogs.com/twodog/p/12135517.html
Copyright © 2011-2022 走看看