1. 程式人生 > 實用技巧 >2020ICPC·小米 網路選拔賽第一場 J.Matrix Subtraction (貪心,二維差分)

2020ICPC·小米 網路選拔賽第一場 J.Matrix Subtraction (貪心,二維差分)

  • 題意:給一個\(nXm\)的矩陣,可以選取\(aXb\)的子矩陣,使子矩陣中的所有元素減一,問最後是否能使矩陣中所有元素變為\(0\).

  • 題解:首先貪心,我們看最左上角的元素,如果\(g[1][1]\ge0\),那麼我們就要對其子矩陣的所有元素減去\(g[1][1]\),然後因為\(g[1][1]\)已經是\(0\)了,假如\(g[1][2]\)存在的話,我們就只能讓它成為子矩陣的左上角然後再對所有子矩陣減去\(g[1][2]\),以此類推,但是直接暴力的話複雜度會炸,我們需要用資料結構來維護,直接用二維差分即可,每次列舉到某個元素的時候判斷它是否不小於\(0\),如果不是就不合法.

  • 程式碼

    :

    int t;
    int n,m,a,b;
    int g[1010][1010];
    int p[1010][1010];
    
    void updata(int i,int j,int ii,int jj,int c){
        p[i][j]+=c;
        p[ii+1][j]-=c;
        p[i][jj+1]-=c;
        p[ii+1][jj+1]+=c;
    }
    
    void solve(){
        n=read(),m=read(),a=read(),b=read();
        for(int i=1;i<=n;++i){
            for(int j=1;j<=m;++j){
                g[i][j]=read();
                p[i][j]=g[i][j]-g[i-1][j]-g[i][j-1]+g[i-1][j-1];
            }
        }
    
        for(int i=1;i<=n;++i){
            for(int j=1;j<=m;++j){
                p[i][j]=p[i][j]+p[i-1][j]+p[i][j-1]-p[i-1][j-1];
                if(p[i][j]<0){
                    puts("QAQ");
                    return;
                }
                else if(p[i][j]>0){
                    if(i+a-1>n || j+b-1>m){
                        puts("QAQ");
                        return;
                    }
                    else updata(i,j,i+a-1,j+b-1,-p[i][j]);
                }
            }
        }
        puts("^_^");
    }
    
    int main() {
        //ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
        t=read();
        while(t--){
            solve();
        }
        return 0;
    }