Cod sursa(job #3330461)

Utilizator coco11coraline kalbfleisch coco11 Data 19 decembrie 2025 17:22:31
Problema Stramosi Scor 0
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.65 kb
#include <bits/stdc++.h>
using namespace std;

#define f first
#define s second
#define int long long

static inline vector<int> manacher_even(const string &s){
    int n = (int)s.size();
    vector<int> d2(n,0);
    int l=0,r=-1;
    for(int i=0;i<n;i++){
        int k=(i>r)?0:min(d2[l+r-i+1],r-i+1);
        while(i-k-1>=0 && i+k<n && s[i-k-1]==s[i+k]) k++;
        d2[i]=k;
        if(i+k-1>r){ l=i-k; r=i+k-1; }
    }
    vector<int> even(max(0LL,n-1LL),0);
    for(int c=0;c<=n-2;c++) even[c]=d2[c+1];
    return even;
}

struct SegTree{
    int n; vector<int> st;
    SegTree(){}
    SegTree(const vector<int>& arr){
        n=(int)arr.size(); st.assign(2*n,INT_MAX);
        for(int i=0;i<n;i++) st[n+i]=arr[i];
        for(int i=n-1;i>0;i--) st[i]=min(st[i<<1],st[i<<1|1]);
    }
    int rangeMin(int l,int r){
        int res=INT_MAX;
        for(l+=n,r+=n;l<=r;l>>=1,r>>=1){
            if(l&1) res=min(res,st[l++]);
            if(!(r&1)) res=min(res,st[r--]);
        }
        return res;
    }
};

signed main(){
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    freopen("origami.in","r",stdin);
    freopen("origami.out","w",stdout);

    int N,M; cin>>N>>M;
    vector<string> A(N);
    for(int i=0;i<N;i++) cin>>A[i];

    vector<vector<int>> rowEven(N);
    for(int i=0;i<N;i++) if(M>=2) rowEven[i]=manacher_even(A[i]);
    vector<vector<int>> colEven(M);
    if(N>=2){
        string col; col.reserve(N);
        for(int j=0;j<M;j++){
            col.clear();
            for(int i=0;i<N;i++) col.push_back(A[i][j]);
            colEven[j]=manacher_even(col);
        }
    }

    vector<SegTree> rowSeg(N), colSeg(M);
    for(int i=0;i<N;i++) if(M>=2) rowSeg[i]=SegTree(rowEven[i]);
    for(int j=0;j<M;j++) if(N>=2) colSeg[j]=SegTree(colEven[j]);

    unsigned long long B=(unsigned long long)max(N,M)+1ULL;
    auto pack=[&](int r1,int c1,int r2,int c2)->unsigned long long{
        return (((unsigned long long)r1*B+(unsigned long long)c1)*B+(unsigned long long)r2)*B+(unsigned long long)c2;
    };

    unordered_set<unsigned long long> vis;
    deque<array<int,4>> dq;
    dq.push_back({0,0,N-1,M-1});
    vis.insert(pack(0,0,N-1,M-1));

    auto push_state=[&](int r1,int c1,int r2,int c2){
        if(r1>r2||c1>c2) return;
        unsigned long long key=pack(r1,c1,r2,c2);
        if(vis.find(key)==vis.end()){
            vis.insert(key);
            dq.push_back({r1,c1,r2,c2});
        }
    };

    while(!dq.empty()){
        auto cur=dq.front();dq.pop_front();
        int r1=cur[0],c1=cur[1],r2=cur[2],c2=cur[3];
        if(M>=2){
            for(int c=c1;c<=c2-1;c++){
                int leftSize=c-c1+1,rightSize=c2-c;
                int need=min(leftSize,rightSize);
                bool ok=true;
                for(int i=r1;i<=r2;i++){
                    if(rowSeg[i].rangeMin(c,c)<need){ ok=false; break; }
                }
                if(!ok) continue;
                if(leftSize<=rightSize) push_state(r1,c+1,r2,c2);
                if(rightSize<=leftSize) push_state(r1,c1,r2,c);
            }
        }
        if(N>=2){
            for(int r=r1;r<=r2-1;r++){
                int topSize=r-r1+1,botSize=r2-r;
                int need=min(topSize,botSize);
                bool ok=true;
                for(int j=c1;j<=c2;j++){
                    if(colSeg[j].rangeMin(r,r)<need){ ok=false; break; }
                }
                if(!ok) continue;
                if(topSize<=botSize) push_state(r+1,c1,r2,c2);
                if(botSize<=topSize) push_state(r1,c1,r,c2);
            }
        }
    }

    cout<<(int)vis.size()<<'\n';
    return 0;
}