昨天刷水累死蒟蒻了。。。
每天一到题解总还是要写的。。。于是就是这个了!
二维RMQ,第一反应是二维线段树,妥妥MLE + TLE
想起来去年市选小题有一道一模一样的,我当时就是写二维线段树,然后MLE0分、、、真是悲剧
发现长度是固定的为n,和动态规划的某个叫单调队列的优化很像:
先求出每一列的某个点向下n个数的最大/小值,然后求出每一行某个点向右的n个单调队列的最大/小值,方法依旧是单调队列。。。
程序写的很烦。。。是照抄网上的。。。(太烦了不想写呢><)
1 /************************************************************** 2 Problem: 1047 3 User: rausen 4 Language: C++ 5 Result: Accepted 6 Time:1604 ms 7 Memory:16600 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 #include <algorithm> 12 13 using namespace std; 14 const int N = 1005; 15 16 int mp[N][N]; 17 int q[N][N], h[N], t[N], Q[N]; 18 int mx[N][N], mn[N][N]; 19 int s, e, a, b, n; 20 21 inline int read(){ 22 int x = 0, sgn = 1; 23 char ch = getchar(); 24 while (ch < '0' || ch > '9'){ 25 if (ch == '-') sgn = -1; 26 ch = getchar(); 27 } 28 while (ch >= '0' && ch <= '9'){ 29 x = x * 10 + ch - '0'; 30 ch = getchar(); 31 } 32 return sgn * x; 33 } 34 35 void getmax(){ 36 for (int i = 1; i <= b; ++i) 37 h[i] = 1, t[i] = 0; 38 for (int i = 1; i <= a; ++i){ 39 for (int j = 1; j <= b; ++j){ 40 while (h[j] <= t[j] && i - q[j][h[j]] >= n) ++h[j]; 41 while (h[j] <= t[j] && mp[q[j][t[j]]][j] <= mp[i][j]) --t[j]; 42 q[j][++t[j]] = i; 43 } 44 e = 0, s = 1; 45 for (int j = 1; j <= b; ++j){ 46 while (s <= e && j - Q[s] >= n) ++s; 47 while (s <= e && mp[q[Q[e]][h[Q[e]]]][Q[e]] <= mp[q[j][h[j]]][j]) --e; 48 Q[++e] = j; 49 mx[i][j] = mp[q[Q[s]][h[Q[s]]]][Q[s]]; 50 } 51 } 52 } 53 54 void getmin(){ 55 for (int i = 1; i <= b; ++i) 56 h[i] = 1, t[i] = 0; 57 for (int i = 1; i <= a; ++i){ 58 for (int j = 1; j <= b; ++j){ 59 while (h[j] <= t[j] && i - q[j][h[j]] >= n) ++h[j]; 60 while (h[j] <= t[j] && mp[q[j][t[j]]][j] >= mp[i][j]) --t[j]; 61 q[j][++t[j]] = i; 62 } 63 e = 0, s = 1; 64 for (int j = 1; j <= b; ++j){ 65 while (s <= e && j - Q[s] >= n) ++s; 66 while (s <= e && mp[q[Q[e]][h[Q[e]]]][Q[e]] >= mp[q[j][h[j]]][j]) --e; 67 Q[++e] = j; 68 mn[i][j] = mp[q[Q[s]][h[Q[s]]]][Q[s]]; 69 } 70 } 71 } 72 73 int main(){ 74 a = read(), b = read(), n = read(); 75 for (int i = 1; i <= a; ++i) 76 for (int j = 1; j <= b; ++j) 77 mp[i][j] = read(); 78 79 getmax(); 80 getmin(); 81 int ans = (int) 1e9; 82 for (int i = n; i <= a; ++i) 83 for (int j = n; j <= b; ++j) 84 ans = min(ans, mx[i][j] - mn[i][j]); 85 printf("%d\n", ans); 86 return 0; 87 }
By Xs酱~ 转载请说明
博客地址:http://www.cnblogs.com/rausen