poj1009 Edge Detection
给一个n * m的矩阵(n * m ≤ 1e9, m ≤ 1e9)A, 求矩阵A'。
定义A'(i, j) = max(abs(A(i, j) - A(u, v))), 其中(u, v)在矩阵内同时在以(i, j)为中心的九宫格范围内。
考虑到矩阵大小,当然不是按照传统方式呈现矩阵,而是用一种流程编码(RLE)的编码方式表示。
编码方式题目已经交代的很清楚了。
看似很棘手的一个题目,对于如此大的数据量感觉似乎无从下手。
注意到题目说明pair数不会超过1e3。
也就是说,相连的重复数字是很多的,这是本题能够被解决的先决条件。
我们定义A(i, j)的位置是(i * width + j)(i, j从0开始)。
我们定义当前pair(i)的最小位置为f(i)。
如果能够知道A'中所有pair的f值,答案即可得到。
然而准确找到所有pair的位置(不重不漏)是困难的,但是找到它们出现的可能位置(允许冗余)则是可行的。
我们断言:A'中所有pair的f值对应的位置(简记为突变位置)若不在某一行的开端,则必在以A中某个突变位置为中心的九宫格范围内。
画图易证。
当突变位置在某一行的起点时候需要特判。
并非所有行都需要特判,只需要在每个pair前两行和后两行进行特判即可,因为中间行周围的元素都和它本身相同。
复杂度落到可控范围内。
这样我们找到所有伪命中点最后再处理一下(去重)就行了,具体实现见代码。
http://poj.org/problem?id=1009
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 5 using namespace std; 6 7 const int maxn = 1e3 + 10; 8 9 struct Point{ 10 int v, len; 11 Point(int v = 0, int len = 0) : v(v), len(len) {} 12 }; 13 14 Point P[maxn], Q[maxn * 30]; 15 int p[maxn]; 16 int k1, k2; 17 int L, N; 18 19 bool inRange(int x, int y) { return x < N / L && x >= 0 && y >= 0 && y < L; } 20 21 bool cmp(Point a, Point b) { return a.len < b.len; } 22 23 int f(int x, int y){ 24 int pos = x * L + y + 1; 25 int l = -1, r = k1 - 1; 26 while(r - l > 1){ 27 int mid = (r + l) >> 1; 28 if(p[mid] >= pos) r = mid; 29 else l = mid; 30 } 31 return P[r].v; 32 } 33 34 int F(int x, int y){ 35 int ans = -1; 36 for(int i = -1; i < 2; i++){ 37 for(int j = -1; j < 2; j++){ 38 int nx = x + i, ny = y + j; 39 if(!inRange(nx, ny)) continue; 40 ans = max(ans, abs(f(nx, ny) - f(x, y))); 41 } 42 } 43 return ans; 44 } 45 46 int Process(int x, int y, int pos){ 47 for(int i = -1; i < 2; i++){ 48 for(int j = -1; j < 2; j++){ 49 int pos1 = pos + i * L + j; 50 int nx = x + i, ny = y + j; 51 if(!inRange(nx, ny)) continue; 52 Q[k2++] = Point(F(nx, ny), pos1); 53 } 54 } 55 } 56 57 void solve(){ 58 k2 = 0; 59 int pos = 0; 60 p[0] = P[0].len; 61 for(int i = 1; i < k1; i++) p[i] = p[i - 1] + P[i].len; 62 for(int i = 0; i < k1; i++){ 63 int x = pos / L, y = pos % L; 64 int nex = pos + P[i].len; 65 int nexrow = (nex - 1) / L; 66 Process(x, y, pos); 67 if(y) Process(x, 0, x * L); 68 if(x != nexrow) Process(nexrow, 0, nexrow * L); 69 pos += P[i].len; 70 } 71 sort(Q, Q + k2, cmp); 72 Q[k2].len = N; 73 for(int i = 0; i < k2; i++){ 74 int j = i; 75 while(i + 1 < k2 && Q[i].v == Q[i + 1].v) ++i; 76 printf("%d %d\n", Q[i].v, Q[i + 1].len - Q[j].len); 77 } 78 } 79 80 int main(){ 81 //freopen("in.txt", "r", stdin); 82 //freopen("out.txt", "w", stdout); 83 while(~scanf("%d", &L) && L){ 84 N = 0; 85 printf("%d\n", L); 86 for(int i = 0; ; i++){ 87 scanf("%d%d", &P[i].v, &P[i].len); 88 N += P[i].len; 89 if(!(P[i].v || P[i].len)){ 90 k1 = i; 91 break; 92 } 93 } 94 solve(); 95 puts("0 0"); 96 } 97 puts("0"); 98 return 0; 99 }