manacher+单调栈:
题解正在写。。。。
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
struct mapp
{
int value;
int rline, rrow;//以此点为对称中心的对称串半径
int r;//最后能得到的最大正方形半径
int tr[5];//四个方向能得到的最大半径
void getans()
{
int t1 = min(rline, rrow); int t2 = min(tr[1], tr[2]); int t3 = min(tr[3], tr[4]);
r = min(t1, t2);
r = min(r, t3);
}
};
mapp t[2010][2010];//记录各点信息
int n, m;
struct roww//维护栈里的能影响那些点
{
int pos, influence, realpos;
};
roww rst[3000];
struct linee
{
int pos, influence, realpos;
};
linee lst[3000];
struct hh
{
int h, pos;
};
hh height[3000];//维护栈里的各种长度
void getrow(int num)//横着一边manacher
{
int circle = 1; int r = 1;
t[num][1].rrow = 1;
for (int i = 2; i <= 2 * m - 1; i++)
{
if (circle + r - 1 > i)
t[num][i].rrow = min(circle + r - 1 - i + 1, t[num][2 * circle - i].rrow);
else
t[num][i].rrow = 1;
while (i + t[num][i].rrow <= 2 * m - 1 && i - t[num][i].rrow >= 1 && t[num][i + t[num][i].rrow].value == t[num][i - t[num][i].rrow].value)
t[num][i].rrow++;
if (i + t[num][i].rrow > circle + r)circle = i, r = t[num][i].rrow;
}
}
void getline(int num)//竖着一边manacher
{
int circle = 1; int r = 1;
t[1][num].rline = 1;
for (int i = 2; i <= 2 * n - 1; i++)
{
if (circle + r - 1 > i)
t[i][num].rline = min(circle + r - 1 - i + 1, t[2 * circle - i][num].rline);
else
t[i][num].rline = 1;
while (i + t[i][num].rline <= 2 * n - 1 && i - t[i][num].rline >= 1 && t[i + t[i][num].rline][num].value == t[i - t[i][num].rline][num].value)t[i][num].rline++;
if (i + t[i][num].rline > circle + r)circle = i, r = t[i][num].rline;
}
}
void getrowans1(int num)//得到<-这个方向的最大距离 上下左右分别代表 1 2 3 4
{
int l = 1; int r = 1; rst[l].pos = 1; rst[l].influence = t[num][1].rline; t[num][1].tr[4] = 1; rst[l].realpos = 1;
int ll = 1; int rr = 1; height[ll].h = t[num][1].rline; height[ll].pos = 1;
for (int i = 2; i <= 2 * m - 1; i++)
{
while (rst[l].realpos + rst[l].influence - 1 < i&&l <= r)l++;//如果栈首不能影响现在这个点那么出栈;
if (l <= r)
{
while (height[ll].pos < rst[l].pos)ll++;//这个是height维护的作用,在能用的那些长度里面我们只能选最小的。(不知道如何维护单调栈的话可以做点题就明白了。
t[num][i].tr[4] = min(height[ll].h, i - rst[l].pos + 1);//这我们取最小值
}
else
t[num][i].tr[4] = 1;
int temppos = i; int temph = t[num][i].rline;
while (l <= r&&rst[r].realpos + rst[r].influence - 1 >= i + t[num][i].rline - 1)temppos = rst[r].pos, r--;//更新栈
while (ll <= rr&&temph <= height[rr].h)rr--;//更新
r++; rr++;
height[rr].h = temph; height[rr].pos = i;
rst[r].influence = t[num][i].rline; rst[r].pos = temppos; rst[r].realpos = i;
}
}//后面的都一样了。。。
void getrowans2(int num)
{
int l = 1; int r = 1; rst[l].pos = 2 * m - 1; rst[l].influence = t[num][2 * m - 1].rline; t[num][2 * m - 1].tr[2] = 1; rst[l].realpos = 2 * m - 1;
int ll = 1; int rr = 1; height[ll].h = t[num][2 * m - 1].rline; height[ll].pos = 2*m-1;
for (int i = 2 * m - 2; i >= 1; i--)
{
while (rst[l].realpos - rst[l].influence + 1 > i&&l <= r)l++;
if (l <= r)
{
while (height[ll].pos > rst[l].pos)ll++;
t[num][i].tr[2] = min(height[ll].h, rst[l].pos - i + 1);
}
else
t[num][i].tr[2] = 1;
int temppos = i; int temph = t[num][i].rline;
while (l <= r&&rst[r].realpos - rst[r].influence + 1 <= i - t[num][i].rline + 1)temppos = rst[r].pos,r--;
while (ll <= rr&&temph <= height[rr].h)rr--;
r++; rr++;
height[rr].h = temph; height[rr].pos = i;
rst[r].influence = t[num][i].rline; rst[r].pos = temppos; rst[r].realpos = i;
}
}
void getans3(int num)
{
int l = 1; int r = 1; lst[l].influence = t[1][num].rrow; t[1][num].tr[1] = 1; lst[l].realpos = 1; lst[l].pos = 1;
int ll = 1; int rr = 1; height[ll].h = t[1][num].rrow; height[ll].pos = 1;
for (int i = 2; i <= 2 * n - 1; i++)
{
while (lst[l].realpos + lst[l].influence - 1 < i&&l <= r)l++;
if (l <= r)
{
while (height[ll].pos < lst[l].pos)ll++;
t[i][num].tr[1] = min(height[ll].h, i - lst[l].pos + 1);
}
else
t[i][num].tr[1] = 1;
int temppos = i; int temph = t[i][num].rrow;
while (l <= r&&lst[r].realpos + lst[r].influence - 1 >= i + t[i][num].rrow - 1)temppos = lst[r].pos, r--;
while (ll<=rr&&temph < height[rr].h)rr--;
r++; rr++;
height[rr].pos = i; height[rr].h = temph;
lst[r].influence = t[i][num].rrow; lst[r].pos = temppos; lst[r].realpos = i;
}
}
void getans4(int num)
{
int l = 1; int r = 1; lst[l].pos = 2 * n - 1; lst[l].influence = t[2 * n - 1][num].rrow; t[2 * n - 1][num].tr[3] = 1; lst[l].realpos = 2 * n - 1;
int ll = 1; int rr = 1; height[ll].h = t[2 * n - 1][num].rrow; height[ll].pos = 2 * n - 1;
for (int i = 2 * n - 2; i >= 1; i--)
{
while (lst[l].realpos - lst[l].influence + 1 > i&&l <= r)l++;
if (l <= r)
{
while (height[ll].pos > lst[l].pos)ll++;
t[i][num].tr[3] = min(height[ll].h, lst[l].pos - i + 1);
}
else
t[i][num].tr[3] = 1;
int temppos = i; int temph = t[i][num].rrow;
while (l <= r&&lst[r].realpos - lst[r].influence + 1 <= i - t[i][num].rrow + 1)temppos = lst[r].pos, r--;
while (ll <= rr&&temph < height[rr].h)rr--;
r++; rr++;
height[rr].h = temph; height[rr].pos = i;
lst[r].influence = t[i][num].rrow; lst[r].pos = temppos; lst[r].realpos = i;
}
}
int main()
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= 2 * n - 1; i += 2)
{
for (int j = 1; j <= 2 * m - 1; j++)
{
scanf("%d", &t[i][j].value);
t[i][j + 1].value = 1000000001;
j++;
}
}
for (int i = 2; i <= 2 * (n - 1); i += 2)
{
for (int j = 1; j <= 2 * m - 1; j++)
{
t[i][j].value = 1000000001;
}
}
for (int i = 1; i <= 2 * n - 1; i++)getrow(i);
for (int i = 1; i <= 2 * m - 1; i++)getline(i);
for (int i = 1; i <= 2 * n - 1; i++)getrowans1(i);
for (int i = 1; i <= 2 * n - 1; i++)getrowans2(i);
for (int i = 1; i <= 2 * m - 1; i++)getans3(i);
for (int i = 1; i <= 2 * m - 1; i++)getans4(i);
long long ans = 0;
for (int i = 1; i <= 2 * n - 1; i++)
{
for (int j = 1; j <= 2 * m - 1; j++)
{
if ((i % 2 == 0 && j % 2 == 1) || (i % 2 == 1 && j % 2 == 0))continue;
t[i][j].getans();
if (t[i][j].value != 1000000001)
ans += ((t[i][j].r - 1) / 2 + 1);
else
ans += t[i][j].r /2;
}
}
printf("%lld\n", ans);
return 0;
}//下面的题解中维护栈里面的各种高度时我们也用的是单调栈来维护的