ZJOI 2009 对称的正方形 RMQ+Manacher
2017-01-22 12:06
316 查看
题目链接:点我点我:-)
题目描述
Orez很喜欢搜集一些神秘的数据,并经常把它们排成一个矩阵进行研究。最近,Orez又得到了一些数据,并已经把它们排成了一个n行m列的矩阵。通过观察,Orez发现这些数据蕴涵了一个奇特的数,就是矩阵中上下对称且左右对称的正方形子矩阵的个数。 Orez自然很想知道这个数是多少,可是矩阵太大,无法去数。只能请你编个程序来计算出这个数。
输入输出格式
输入格式:
文件的第一行为两个整数n和m(n,m <= 1000)。接下来n行每行包含m个正整数,表示Orez得到的矩阵。
输出格式:
文件中仅包含一个整数answer,表示矩阵中有answer个上下左右对称的正方形子矩阵。
思路:
1. 把矩阵变成(2n-1)*(2m-1)的,即在数字中间补上0
2.(Manacher算法)定义lx[][], ly[][]数组分别表示对于每个矩阵中的数,它的左右(上下)的最长延伸回文串的长度
3.定义left[][]数组表示对于每个矩阵中的数,以它为中心,最多可以向左边延伸的半个矩形(保证上下回文)的长度(长度应小于所有在范围内的ly[][]的最小值)
4. 那么对于left[i]数组,它的左边界(j-left[i])是递增不减的,所以可以结合RMQ在O(n2)的时间内求出来
5. 所以right[][], up[][], down[][]数组定义类似
6. 那么最终的答案为min(left[][], right[][], up[][], down[][])的和再减去包含0的部分!
感想:
很遗憾本题并没有自己想出来,本来是拿它当基础练手的,洛谷的难度评定是普及+提高-,还是觉得有点难度的。这种题目如果自己可以想出来一定是个大飞跃。
另:以后写代码力争简洁,把代码写得像有水平的人写的!
代码:
题目描述
Orez很喜欢搜集一些神秘的数据,并经常把它们排成一个矩阵进行研究。最近,Orez又得到了一些数据,并已经把它们排成了一个n行m列的矩阵。通过观察,Orez发现这些数据蕴涵了一个奇特的数,就是矩阵中上下对称且左右对称的正方形子矩阵的个数。 Orez自然很想知道这个数是多少,可是矩阵太大,无法去数。只能请你编个程序来计算出这个数。
输入输出格式
输入格式:
文件的第一行为两个整数n和m(n,m <= 1000)。接下来n行每行包含m个正整数,表示Orez得到的矩阵。
输出格式:
文件中仅包含一个整数answer,表示矩阵中有answer个上下左右对称的正方形子矩阵。
思路:
1. 把矩阵变成(2n-1)*(2m-1)的,即在数字中间补上0
2.(Manacher算法)定义lx[][], ly[][]数组分别表示对于每个矩阵中的数,它的左右(上下)的最长延伸回文串的长度
3.定义left[][]数组表示对于每个矩阵中的数,以它为中心,最多可以向左边延伸的半个矩形(保证上下回文)的长度(长度应小于所有在范围内的ly[][]的最小值)
4. 那么对于left[i]数组,它的左边界(j-left[i])是递增不减的,所以可以结合RMQ在O(n2)的时间内求出来
5. 所以right[][], up[][], down[][]数组定义类似
6. 那么最终的答案为min(left[][], right[][], up[][], down[][])的和再减去包含0的部分!
感想:
很遗憾本题并没有自己想出来,本来是拿它当基础练手的,洛谷的难度评定是普及+提高-,还是觉得有点难度的。这种题目如果自己可以想出来一定是个大飞跃。
另:以后写代码力争简洁,把代码写得像有水平的人写的!
代码:
#include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<iostream> #include<algorithm> using namespace std; #define LL long long #define pb push_back #define Set(a, v) memset(a, v, sizeof(a)) #define For(i, a, b) for(int i = (a); i <= (int)(b); i++) #define Forr(i, a, b) for(int i = (a); i >= (int)(b); i--) #define LOG (10+5) #define MAXN (2000+5) int f[MAXN][MAXN]; int map[MAXN][MAXN], lx[MAXN][MAXN], ly[MAXN][MAXN]; void read(int &x){ char ch = getchar(); while(ch < '0' || ch > '9') ch = getchar(); x = 0; while(ch >= '0' && ch <= '9'){ x = x*10+ch-'0'; ch = getchar(); } } int s[MAXN], Min[MAXN][LOG], Log[MAXN]; void Manacher(int *len, int n){ int p0 = 0; For(i, 1, n){ int pos = p0+len[p0]; if(pos > i && len[2*p0-i]<(pos-i)) len[i] = len[2*p0-i]; else{ if(pos > i) len[i] = pos-i; while(i+len[i] < n && i-len[i] > 1 && s[i+len[i]+1]==s[i-len[i]-1]) ++len[i]; p0 = i; } } } void makeRMQ(int x[MAXN][MAXN], int h, int n){ Set(Min, 0x3f); For(i, 1, n) Min[i][0] = x[i][h]; For(j, 1, 11) For(i, 1, n){ if((i+(1<<j)-1) > n) break; Min[i][j] = min(Min[i][j-1], Min[i+(1<<(j-1))][j-1]); } } int query(int L, int R){ int k = Log[R-L+1]; return min(Min[L][k], Min[R-(1<<k)+1][k]); } int main(){ int n, m; read(n); read(m); For(i, 2, n) Log[i] = Log[i>>1]+1; For(i, 1, n) For(j, 1, m) read(map[i*2-1][j*2-1]); n = n*2-1, m = m*2-1; For(i, 1, n){ For(j, 1, m) s[j] = map[i][j]; Manacher(lx[i], m); } For(i, 1, m){ For(j, 1, n) s[j] = map[j][i]; Manacher(ly[i], n); } Set(f, 0x3f); For(i, 1, n){ makeRMQ(ly, i, m); int v = 1; For(j, 1, m){ while(v<j && query(v, j) < (j-v)) v++; f[i][j] = min(f[i][j], j-v); } v = m; Forr(j, m, 1){ while(v>j && query(j, v) < (v-j)) v--; f[i][j] = min(f[i][j], v-j); } } For(i, 1, m){ makeRMQ(lx, i, n); int v = 1; For(j, 1, n){ while(v<j && query(v, j) < (j-v)) v++; f[j][i] = min(f[j][i], j-v); } v = n; Forr(j, n, 1){ while(v>j && query(j, v) < (v-j)) v--; f[j][i] = min(f[j][i], v-j); } } int ans = 0; For(i, 1, n) For(j, 1, m){ if((i&1)&&(j&1)) ans += (f[i][j]>>1)+1; else if(!(i&1) && !(j&1)) ans += (f[i][j]+1)>>1; } printf("%d\n", ans); return 0; }
相关文章推荐
- ZJOI 2009 对称的正方形 ST+Manacher
- [ZJOI2009对称的正方形]ST+Manacher
- [luoguP2601] [ZJOI2009]对称的正方形(二维Hash + 二分 || Manacher)
- NKOJ 2663 (ZJOI 2009)对称的正方形(Manacher)
- [BZOJ1414][ZJOI2009]对称的正方形(manacher+单调栈+二分)
- 【ZJOI 2009 Day2】对称的正方形
- bzoj 1414: [ZJOI2009]对称的正方形
- bzoj 1414: [ZJOI2009]对称的正方形 manacher算法+單調隊列
- bzoj1414 [ZJOI2009]对称的正方形 && bzoj3705 对称的正方形
- 【BZOJ1414/3705】[ZJOI2009]对称的正方形 二分+hash
- bzoj 1414: [ZJOI2009]对称的正方形
- 1414: [ZJOI2009]对称的正方形 Hash+二分
- BZOJ 1414 ZJOI2009 对称的正方形 Hash+二分
- [BZOJ]1414: [ZJOI2009]对称的正方形 二分+hash
- bzoj1414 [ZJOI2009]对称的正方形
- bzoj1414: [ZJOI2009]对称的正方形
- bzoj1414 [ZJOI2009]对称的正方形(二分答案+二维哈希)
- bzoj 1414 && bzoj 3705: [ZJOI2009]对称的正方形(二维Hash)
- [除草]BZOJ 1414 [ZJOI2009]对称的正方形
- 【bzoj 1414】对称的正方形 单调队列+manacher