Red Huang

Red Huang

Codeforces Round #219(Div. 2)D. 長方形の数え上げは楽しいです

インターネット上では、みんなが最初に前処理をすると言っていますが、どのように前処理をすればいいのかがポイントです。私はわかりません〜〜〜

ただ、ここで少し理解しました

image

1. 各セルとその上のセルがいくつの長方形を構成できるかを計算します。1 に出会った場合は 0 に変える必要があります。

2. 次に、四方向の大枚舞台 u、l、d、r を利用して、右下の点を使用してこの四方向内のセルと最大でいくつの長方形を構成できるかを計算します。

したがって、ちょうど先ほどの 1 つ目のステップで計算されたポイントに現在の最小値を加えるだけで、0 に出会った場合は再度計算しないでください。

3.u、l、d-1、r u、l、d、r-1 の数を追加します。もちろん、これらはすでに処理されています(これらの処理済みのポイントは、処理する必要のあるポイントもすべて処理されています(DP の概念))し、重複部分があるため、u、l、d-1、r-1 を引く必要があります。

/\*  
 \* GCA : "Computer is artificial subject absolutely,Math is God"  
 \*/  
#include <iostream>  
#include <cstdio>  
#include <cstring>  
#include <algorithm>  
#include <cmath>  
#include <climits>  
#include <vector>  
#include <set>  
#include <map>  
#include <queue>  
#include <cctype>  
#include <utility>  
#include <ctime>  
using namespace std;  
#ifdef DEBUG  
#define VAR(a,b) \_\_typeof(b) a=(b)  
#define debug(...) printf("DEBUG: "),printf(\_\_VA\_ARGS\_\_)  
#else  
#define VAR(a,b) \_\_typeof(b) a=(b)  
#define debug(...)  
#endif  
typedef unsigned int uint;  
typedef long long int Int;  
typedef unsigned long long int UInt;  
#define Set(a,s) memset(a,s,sizeof(a))  
#define Pln() printf("\\n")  
#define For(i,x)for(int i=0;i<x;i++)  
#define CON(x,y) x##y  
#define M 45  
#define PB push\_back  
#define oo INT\_MAX  
#define FOR(a,b) for(VAR(a,(b).begin());a!=(b).end();++a)  
#define eps 1e-9  
#define X first  
#define Y second  
inline bool xdy(double x,double y){return x>y+eps;}  
inline bool xddy(double x,double y){return x>y-eps;}  
inline bool xcy(double x,double y){return x<y-eps;}  
inline bool xcdy(double x,double y){return x<y+eps;}  
const Int mod=1000000007;  
int n,m,q;  
char mz\[M\]\[M\];  
int dp\[M\]\[M\]\[M\]\[M\];  
int cnt\[M\]\[M\];  
void pre(){  
    Set(dp,0);  
    Set(cnt,0);  
    for(int i=1;i<=n;i++){  
        for(int j=1;j<=m;j++){  
            if(mz\[i-1\]\[j-1\]=='0')cnt\[i\]\[j\]=cnt\[i-1\]\[j\]+1;  
            else cnt\[i\]\[j\]=0;  
        }  
    }  
    for(int u=1;u<=n;u++){  
        for(int l=1;l<=m;l++){  
            for(int d=u;d<=n;d++){  
                for(int r=l;r<=m;r++){  
                    int minn=d-u+1;  
                    int all=0;  
                    for(int k=r;k>=l;k--){  
                        minn=min(minn,cnt\[d\]\[k\]);  
                        if(minn==0)break;  
                        all+=minn;  
                    }  
                    dp\[u\]\[l\]\[d\]\[r\]=dp\[u\]\[l\]\[d-1\]\[r\]+dp\[u\]\[l\]\[d\]\[r-1\]-dp\[u\]\[l\]\[d-1\]\[r-1\]+all;  
                }  
            }  
        }  
    }  
}  
int main() {  
    ios\_base::sync\_with\_stdio(0);  
    while(~scanf("%d%d%d",&n,&m,&q)){  
        for(int i=0;i<n;i++){  
            scanf("%s",mz\[i\]);  
        }  
        pre();  
        while(q--){  
            int a,b,c,d;  
            scanf("%d%d%d%d",&a,&b,&c,&d);  
            printf("%d\\n",dp\[a\]\[b\]\[c\]\[d\]);  
        }  
    }  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
}  

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。