Cod sursa(job #1299778)

Utilizator Al3ks1002Alex Cociorva Al3ks1002 Data 23 decembrie 2014 21:03:27
Problema Range minimum query Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 3.51 kb
#include<cstdio>
#include<fstream>
#include<iostream>
#include<iomanip>
#include<algorithm>
#include<vector>
#include<bitset>
#include<deque>
#include<queue>
#include<set>
#include<map>
#include<cmath>
#include<cstring>
#include<ctime>
#include<cstdlib>
#include<unordered_map>

#define ll long long
#define pb push_back
#define mp make_pair
#define pii pair<int,int>
#define pll pair<ll,ll>

using namespace std;

const int nmax = 1005;
const int lmax = 10;

int n, i, j, l, P, ans, w[nmax], p[2 * nmax];
short int row[nmax][nmax], col[nmax][nmax];
short int rmqc[lmax][nmax], rmql[nmax][lmax][nmax];
char a[nmax][nmax], s[nmax], t[2 * nmax];

void manacher()
{
    int N = 0;
    t[0] = '$';
    for(int i = 0; i < n; i++)
    {
        t[++N] = s[i];
        p[N] = 1;
        t[++N] = '$';
    }

    int C = 0;
    int R = 0;
    for(int i = 1; i < N; i++)
    {
        int mirror = 2 * C - i;

        if(i <= R)
            p[i] = min(p[mirror], R - i + 1);

        int l = i - p[i] + 1;
        int r = i + p[i] - 1;

        while(l - 2 >= 1 && r + 2 <= N && t[l - 2] == t[r + 2])
        {
            l -= 2;
            r += 2;
            p[i] += 2;
        }

        if(r > R)
        {
            R = r;
            C = i;
        }

        if(i & 1) w[(i + 1) / 2] = p[i];
    }
}

short int get_minc(int coll, int x, int y)
{
    int dif = y - x + 1;
    int l = log2(dif + 0.5);

    return min(rmql[coll][l][x], rmql[coll][l][y - (1 << l) + 1]);
}

short int get_minr(int x, int y)
{
    int dif = y - x + 1;
    int l = log2(dif + 0.5);

    return min(rmqc[l][x], rmqc[l][y - (1 << l) + 1]);
}

bool check(int x, int i, int j)
{
    if(j - x / 2 < 1 || j + x / 2 > n || i - x / 2 < 1 || i + x / 2 > n) return 0;
    return min(get_minc(j, i - x / 2, i + x / 2), get_minr(j - x / 2, j + x / 2)) >= x;
}

int main()
{
    freopen("pscpld2d.in", "r", stdin);
    freopen("pscpld2d.out", "w", stdout);

    scanf("%d", &n);

    for(i = 1; i <= n; i++)
        scanf("%s", a[i] + 1);

    for(i = 1; i <= n; i++)
    {
        for(j = 1; j <= n; j++)
            s[j - 1] = a[i][j];

        manacher();

        for(j = 1; j <= n; j++)
            row[i][j] = w[j];
    }

    for(j = 1; j <= n; j++)
    {
        for(i = 1; i <= n; i++)
            s[i - 1] = a[i][j];

        manacher();

        for(i = 1; i <= n; i++)
            col[i][j] = w[i];
    }

    for(j = 1; j <= n; j++)
    {
        for(i = 1; i <= n; i++)
            rmql[j][0][i] = row[i][j];
        for(l = 1, P = 2; P <= n; l++, P *= 2)
            for(i = 1; i + P - 1 <= n; i++)
                rmql[j][l][i] = min(rmql[j][l - 1][i], rmql[j][l - 1][i + P / 2]);
    }

    for(i = 1; i <= n; i++)
    {
        for(j = 1; j <= n; j++)
            rmqc[0][j] = col[i][j];
        for(l = 1, P = 2; P <= n; l++, P *= 2)
            for(j = 1; j + P - 1 <= n; j++)
                rmqc[l][j] = min(rmqc[l - 1][j], rmqc[l - 1][j + P / 2]);

        for(j = 1; j <= n; j++)
        {
            int l = 1;
            int r = (n + 1) / 2;
            int sol = 0;
            while(l <= r)
            {
                int m = (l + r) / 2;
                if(check(2 * m - 1, i, j))
                {
                    sol = 2 * m - 1;
                    l = m + 1;
                }
                else r = m - 1;
            }
            ans += (sol + 1) / 2;
        }
    }

    printf("%d\n", ans);

    return 0;
}