我不是說了難度要平均值了嗎!-SDUT某選拔賽題

Problem Description

“給出一個 n * m 大小的矩形 , 然後每次給次 x1 , y1 , x2 , y2 四個數。”
“那個…等等麥露!是不是有什麼不太對的對方?w(゚Д゚)w” “嗯?應該沒有吧。”
“我們是hunter吧,我們應該是hunter的吧,爲什麼我們4人要在這裏做這些奇怪的問題呀!”
“沒關係的,這題很普通,話說這不是烈娜接下的委託嗎。” “雖然是這樣的…不過這明顯不在我的知識範圍內了呀,說什麼要求以 ( x1 , y1
) 爲左上角和 ( x2 , y2 ) 爲右下角矩陣內數的異或和,異或是個是什麼東西,加減就已經是我的極限了啊!”
“emmm…異或就是異或了,那個XOR呀,^呀,二進制運算之類的” “說的再清楚一點呀!” “比如…比如…
那個來代表異或運算,00=0 , 0^1=1 , 1^0=1 , 1^1=0 ,
題面上也說了矩陣裏只有0和1了,這樣就可以做了吧,大概”

Input

第一行輸入兩個數n,m表示矩陣的大小(0<n<=2e3,0<m<=2e3) 接下來的n行每行有m個整數,表示每個位置的數a(0<=a<=1)
接下來一行輸入一個q(0<q<=1e5),代表q次詢問 每次給出x1 y1 x2 y2(0<x1<=x2<=n,0<y1<=y2<=m)

Output

輸出有q行,對應每一次詢問的答案.

Sample Input

2 2 0 1 0 1 1 1 1 1 1

這道題要說難其實真不難,只要搞懂了多個數據異或和的運算剩下的就好辦了
多個數據的異或和相當於這些數據的和對2取餘,例如1,1,1的異或和是3%2 = 1
1,0,1,0的異或和是2%2 = 0
搞懂這些之後,我們只需要將範圍內的數值和運算一下即可。但是如果我們一個一個相加的話,會導致超時,所以這裏需要使用一個小技巧(鬼知道大佬們都多早就知道這個小技巧了…)
例如我們如果要求
1 1 0
0 1 0
1 0 1
這個矩陣從左上角到右下角的數值和,那麼我們可以先把這個矩陣從左加到右,變成下面這個樣子
1 2 2
0 1 1
1 1 2
再將得到的矩陣豎着從上加到下
1 2 2
1 3 3
2 4 5
那麼我們對得到的這個矩陣做一下簡單的四則運算,就可以得到我們想要的範圍內的值了
比如我們想要原矩陣(2,2)-(3,3)的值,我們只需要用(3,3)-(3,3-2)-(3-2,3)+(2-1,2-1)這個算式便可以算出原矩陣(2,2)-(3,3)的值了
比如這裏就是5-2-2+1=2

下面放出我的ac代碼

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

int main()
{
    
    int n,m,q,x1,x2,y1,y2,sum;
    int b;
    cin>>n>>m;
    int a[2005][2005];	//橫着相加的儲存數組
    int c[2005][2005];	//豎着相加的儲存數組
    memset(a,0,sizeof(a));
    memset(c,0,sizeof(c));
    for(int i = 1;i<=n;i++)
        for(int j = 1;j<=m;j++){
            scanf("%d",&b);
            a[i][j] = a[i][j-1]+b;	//輸入並橫着相加
        }
    for(int i = 1;i<=n;i++)
        for(int j = 1;j<=m;j++)
            c[i][j] = c[i-1][j]+a[i][j];	//豎着相加
    cin>>q;
    while(q--)
    {
        scanf("%d %d %d %d",&x1,&y1,&x2,&y2);
        sum =c[x2][y2]-c[x2][y1-1]-c[x1-1][y2]+c[x1-1][y1-1];
        cout<<sum%2<<endl;
    }
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章