您的位置:首页 > 其它

【MZ】CF 363E #211 (Div. 2)

2013-11-12 02:16 323 查看

problem:

给一个n*m的矩阵,每个cell有个值。定义一种cricle,半径为r(这个我就不解释了。。)。选两个没有公共cell的circle使其和最大,并输出有多少中选择。

think

1.预处理每个circle的值。n^3. 这个先存一下每一列sum(a(i,1) + a(i,2) + …… + a(i,j))。然后找到圆心为(i,j)这个circle的第ii行时,可以O(1)得到他的横向长度。

2.预处理每行的左端最大circle值和右端最大circle值。n^2. max(val(i,1), val(i,2), ……, val(i,j)) 和 the quatity of (val[i][jj] == L[i][j])

3.预处理nn[i] = j. n^2. 表示i*i+j*j<=r*r.用于预处理下面的diff数组。方法暴力搞就行。

4.预处理diff[i] = j. n^3. 表示当圆心列数与某circle相差i时,行数最少相差j。方法暴力搞就行。

default:

1.如果不予处理diff数组,而用sqrt(2*r*2*r - (i-ii)*(i-ii)) 这样,会一直 WA 在 test20.

2.num会爆int

code

const int N = 505;
int n, m, r;
int a

;//the input
int val

;//every circle value of i,j
int lft

;//sum(a(i,1) + a(i,2) + …… + a(i,j)) for the array of "val"
int L

;//max(val(i,1), val(i,2), ……, val(i,j))
LL numL

;//the quatity of (val[i][jj] == L[i][j])
int R

;//max(val(i,n), val(i,n-1), ……, val(i,j))
LL numR

;//the quatity of (val[i][jj] == R[i][j])
int nn
;//nn[i] = j; //i*i + j*j <= r
int diff
;//

int main(){
    memset(lft, 0, sizeof(lft));
    memset(val, 0, sizeof(val));
    memset(L, 0, sizeof(L));
    memset(R, 0, sizeof(R));
    memset(numL, 0, sizeof(numL));
    memset(numR, 0, sizeof(numR));
    scanf("%d%d%d", &n, &m, &r);
    for(int i = 1; i <= n; ++i){
        for(int j = 1; j <= m; ++j){
            scanf("%d", &a[i][j]);
            lft[i][j] = lft[i][j-1] + a[i][j];
        }
    }
    memset(val, 0, sizeof(val));
    for(int i = r+1; i <= n-r; ++i){
        for(int j = r+1; j <= m-r; ++j){
            for(int ii = - r; ii <= r; ++ii){
                int jj = sqrt(r*r - ii*ii);
                val[i][j] += lft[i+ii][j+jj] - lft[i+ii][j-jj-1];
            }
            if(val[i][j] == L[i][j-1]) {
                L[i][j] = L[i][j-1];
                numL[i][j] = numL[i][j-1] + 1LL;
            }
            else if(val[i][j] < L[i][j-1]){
                L[i][j] = L[i][j-1];
                numL[i][j] = numL[i][j-1];
            }
            else {
                L[i][j] = val[i][j];
                numL[i][j] = 1LL;
            }
        }
    }
    for(int i = r+1; i <= n-r; ++i){
        for(int j = m-r; j >= r+1; --j){
            if(val[i][j] == R[i][j+1]) {
                R[i][j] = R[i][j+1];
                numR[i][j] = numR[i][j+1] + 1LL;
            }
            else if(val[i][j] < R[i][j+1]){
                R[i][j] = R[i][j+1];
                numR[i][j] = numR[i][j+1];
            }
            else {
                R[i][j] = val[i][j];
                numR[i][j] = 1LL;
            }
        }
    }
    memset(nn, 0, sizeof(nn));
    for(int i = 0; i <= r; ++i){
        int j = 0;
        while(j*j + i*i <= r*r) ++j;
        nn[i] = j-1;
    }
    for(int i = 0; i <= r*2; ++i){
        int tmp = 0;
        for(int j = 0; j <= r; ++j){
            if(j > r || j < i - r) continue;
            tmp = max(tmp, nn[j] + 1 + nn[abs(i-j)]);
        }
        diff[i] = tmp;
    }
    int ans = 0;
    LL num = 0LL;
    for(int i = r+1; i <= n-r; ++i){
        for(int j = r+1; j <= m-r; ++j){
            for(int ii = r+1; ii <= n-r; ++ii){
                int tmp;
                if(ii-i-1 >= 2*r || i - ii-1 >= 2*r){
                    tmp = val[i][j] + L[ii][m-r];
                    if(tmp==ans){
                        num += numL[ii][m-r];
                    }
                    else if(tmp > ans){
                        ans = tmp;
                        num = numL[ii][m-r];
                    }
                    continue;
                }
                int tmpii = abs(i - ii);
                int tmpjj = diff[tmpii];

                int jj = j - tmpjj;
                if(jj >= r+1) {
                    tmp = val[i][j] + L[ii][jj];
                    if(tmp==ans){
                        num += numL[ii][jj];
                    }
                    else if(tmp > ans){
                        ans = tmp;
                        num = numL[ii][jj];
                    }
                }
                jj = j + tmpjj;
                if(jj <= m-r){
                    tmp = val[i][j] + R[ii][jj];
                    if(tmp==ans){
                        num += numR[ii][jj];
                    }
                    else if(tmp > ans){
                        ans = tmp;
                        num = numR[ii][jj];
                    }
                }
            }
        }
    }
    if(num==0) puts("0 0");
    else printf("%d %I64d\n", ans, num/2LL);
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: