【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; }
相关文章推荐