1. 程式人生 > >POJ2155/LNSYOJ113 Matrix【二維樹狀陣列+差分】【做題報告】

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)格式為

y1≤y2≤n)">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]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]=(tree[i][j]+val)%2;
 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=(ans+tree[i][j])%2;
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\n",ask(x,y));
40             }
41         }
42     }
43     return 0;
44 }

 

 

By  淺夜_MISAKI