poj2155 Matrix

二维树状数组加差分

这道题需要加个差分,差分个人理解就是把正常一个数组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,再累加前缀和能满足(图片出处在水印)。

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

  #include<cstdio>
  #include<algorithm>
  #include<cstring>
  int t,n,k,x1,y1,x2,y2;
  int e[1007][1007];
  char ch[5];
  void change(int x,int y,int val)
  {
     for(int i=x;i<=n;i+=i&(-i))
         for(int j=y;j<=n;j+=j&(-j))
            e[i][j]=(e[i][j]+val)%2;
 }
 int ask(int x,int y)
 {
     int ans=0;
     for(int i=x;i;i-=i&(-i))
         for(int j=y;j;j-=j&(-j))
             ans=(ans+e[i][j])%2;
     return ans;
 }
 int main()
 {
     scanf("%d",&t);
     while(t--)
     {
         memset(e,0,sizeof(e));
         scanf("%d%d",&n,&k);
         for(int i=1;i<=k;i++)
         {
             scanf("%s",ch);
             if(ch[0]=='C')
             {
                 scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
                 change(x1,y1,1),change(x2+1,y2+1,1),change(x1,y2+1,1),change(x2+1,y1,1);
             }else if(ch[0]=='Q')
             {
             	 int x,y;
                 scanf("%d%d",&x,&y);
                 printf("%d\n",ask(x,y));
             }
         }
     }
     return 0;
 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值