zoukankan      html  css  js  c++  java
  • bzoj 1414: [ZJOI2009]对称的正方形

    传送门

    我有效率这种东西吗,那是什么,可以吃吗

    先对每行每列跑manacher,然后需要求出每个点可以向四周扩展的最大距离,

    考虑单独一行,对于每个i只需求出它前面距它最远的一个j满足i-j+1>=min(rad[j]~rad[i])

    这个可以用单调队列维护,维护一个rad值单增的单调队列,同时记录队首最后一个被弹出去的元素的位置,就可以维护了。

    那么对于每行每列都正反跑一遍然后每个点取min,即每个格子对它上下左右预计能扩展的最大正方形边长取min即可。

    需要注意这种整个补了一些奇怪的东西的时候有些格子是没有贡献的,计算答案的时候不考虑它。

    //Achen
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<vector>
    #include<queue>
    #include<cmath>
    #include<ctime>
    const int N=2007; 
    typedef long long LL;
    using namespace std;
    int n,m,a[N][N],mx[N][N],rad1[N][N],rad2[N][N];
    
    template<typename T> void read(T &x) {
        T f=1; x=0; char ch=getchar();
        while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
        if(ch=='-') f=-1,ch=getchar();
        for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
    }
    
    int tot,tp[N],rad[N],que[N],ql,qr,last;
    void work(int id,int f) {
        tot=(f==1?m:n);
        memset(rad,0,sizeof(rad));
        for(int i=1;i<=tot;i++) tp[i]=(f==1?a[id][i]:a[i][id]);
        for(int i=1,j,k=0;i<=tot;) {
            while(tp[i-k-1]==tp[i+k+1]) k++;
            rad[i]=k;
            for(j=1;j<=k&&rad[i-j]!=rad[i]-j;j++)
                rad[i+j]=min(rad[i-j],rad[i]-j);
            k=max(k-j,0);
            i+=j;
        }
        for(int i=1;i<=tot;i++)
            if(f==1) rad1[id][i]=rad[i];
            else rad2[i][id]=rad[i];
    
    }
    
    void solve(int id,int f) {
        tot=(f==1?m:n);
        for(int i=1;i<=tot;i++) 
            if(f==1) rad[i]=rad2[id][i]; 
            else rad[i]=rad1[i][id];
        ql=1; qr=0; last=0;
        for(int i=1;i<=tot;i++) {
            while(ql<=qr&&rad[que[qr]]>=rad[i]) qr--;
            que[++qr]=i;
            while(ql<=qr&&(i-que[ql])+1>rad[que[ql]]) last=que[ql],ql++;
            int now=0;
            if(ql<=qr&&(i-que[ql])+1<=rad[que[ql]]) 
                now=min(rad[que[ql]],i-last);
            if(f==1) mx[id][i]=min(mx[id][i],now);
            else mx[i][id]=min(mx[i][id],now);
        }
        ql=1; qr=0; last=tot+1;
        for(int i=tot;i>=1;i--) {
            while(ql<=qr&&rad[que[qr]]>=rad[i]) qr--;
            que[++qr]=i;
            while(ql<=qr&&que[ql]-i+1>rad[que[ql]]) last=que[ql],ql++;
            int now=0;
            if(ql<=qr&&(que[ql]-i)+1<=rad[que[ql]]) 
                now=min(rad[que[ql]],last-i);
            if(f==1) mx[id][i]=min(mx[id][i],now);
            else mx[i][id]=min(mx[i][id],now);
        }
    }
    
    int main() {
    #ifdef DEBUG
        freopen("1.in","r",stdin);
        freopen("1.out","w",stdout);
    #endif
        read(n); read(m);
        LL ans=n*m;
        for(int i=1;i<=n;i++) {
            for(int j=1;j<=2*m+1;j++) a[i*2-1][j]=-1;
            for(int j=1;j<=m;j++) {
                a[i*2][j*2-1]=-1;
                read(a[i*2][j*2]);
            }
            a[i*2][m*2+1]=-1;
            if(i==n) for(int j=1;j<=2*m+1;j++) a[n*2+1][j]=-1;
        }
        n=2*n+1; m=2*m+1; 
        memset(mx,127,sizeof(mx));
        for(int i=1;i<=n;i++) work(i,1);
        for(int i=1;i<=m;i++) work(i,-1);
        for(int i=1;i<=n;i++) solve(i,1);
        for(int i=1;i<=m;i++) solve(i,-1);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++) {
                if(a[i][j]==-1&&(a[i-1][j]!=-1||a[i][j-1]!=-1)) continue;
                if(a[i][j]!=-1&&mx[i][j]%2==0) mx[i][j]--;
                else if(a[i][j]==-1&&mx[i][j]&1) mx[i][j]--; 
                if(mx[i][j]/2)
                ans+=mx[i][j]/2;
            }
        printf("%lld
    ",ans);
        return 0;
    }
    /*
    5 5
    4 2 4 4 4 
    3 1 4 4 3 
    3 5 3 3 3 
    3 1 5 3 3 
    4 2 1 2 4 
    */
    View Code
  • 相关阅读:
    centos pptp client 配置
    hadoop hdfs 权限修改
    cdh Host Monitor 启动失败
    cdh yarn 启动失败
    hive 存储
    docker修改默认存储位置
    centos新增磁盘
    zookeeper服务部署数量
    实时人群计算——设想
    docker容器多服务——Supervisor
  • 原文地址:https://www.cnblogs.com/Achenchen/p/8322240.html
Copyright © 2011-2022 走看看