2023河南萌新联赛第(五)场 K.01BFS

传送门

https://ac.nowcoder.com/acm/contest/62977/K

题目大意

给定一个 n × m n \times m n×m 的矩阵 G G G ,每个点有权值 G i , j G_{i,j} Gi,j,开始可以选择一个方向跳,每次跳跃只能跳到严格大于当前点权的位置。跳跃过程中总共可以转一次方向,求最多可以跳几次。

题解

不妨枚举它的转弯点和它的方向,
例如,从上方来到转弯点,
它可以选择往左或往右跳(或者往前跳,即放弃转弯机会)。
在这里插入图片描述
剩下的就是单向操作了,可以预处理。
问题转化为了如何处理一行或一列的最长单调 下降/上升 子序列。
对于这个问题,要求 n l o g n n logn nlogn n n n \sqrt n nn 解决,考虑优化。
理想的,有一条优秀的序列,将它直接插入该序列中,查找比它小的个数就可以得到最大的解。
显然的,该序列是单调的,且需要有尽可能多的数,在满足单调性的同时,我们要使两两差尽可能小。
故每次维护只需要把一个大于或等于当前权值的数代替即可。如果大于顶部元素,直接加入即可。
对于这个问题,跑 8 8 8 次查询就可以维护好了。

参考代码

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int n,m,T;
int st[N];
int ans;
int main()
{
    cin>>T;
    while(T--)
    {
        ans=0;
        scanf("%d%d",&n,&m);
        vector<vector<int>>v(n+1,vector<int>(m+1));
        vector<vector<int>>v1(n+1,vector<int>(m+1));  //横着从左往右递增
        vector<vector<int>>v2(n+1,vector<int>(m+1));  //横着从右往左递增
        vector<vector<int>>v3(n+1,vector<int>(m+1));  //横着从左往右递减
        vector<vector<int>>v4(n+1,vector<int>(m+1));  //横着从右往左递减
        vector<vector<int>>v5(n+1,vector<int>(m+1));  //横着从下往上递增
        vector<vector<int>>v6(n+1,vector<int>(m+1));  //横着从上往下递增
        vector<vector<int>>v7(n+1,vector<int>(m+1));  //横着从下往上递减
        vector<vector<int>>v8(n+1,vector<int>(m+1));  //横着从上往下递减
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                scanf("%d",&v[i][j]);
        for(int i=1;i<=n;i++)
        {
            int tot=0;
            st[tot]=0;
            for(int j=1;j<=m;j++)
            {
                if(v[i][j]>st[tot])
                {
                    st[++tot]=v[i][j];  
                    v1[i][j]=tot-1;
                }
                else
                {
                    int id=lower_bound(st+1,st+tot+1,v[i][j])-st;   
                    st[id]=v[i][j];
                    v1[i][j]=id-1;
                }
            }
        }
        for(int i=1;i<=n;i++)
        {
            int tot=0;
            st[tot]=-N;
            for(int j=1;j<=m;j++)
            {
                if(-v[i][j]>st[tot])
                {
                    st[++tot]=-v[i][j];  
                    v3[i][j]=tot-1;
                }
                else
                {
                    int id=lower_bound(st+1,st+tot+1,-v[i][j])-st;   
                    st[id]=-v[i][j];
                    v3[i][j]=id-1;
                }
            }
        }
        for(int i=1;i<=n;i++)
        {
            int tot=0;
            st[tot]=0;
            for(int j=m;j>=1;j--)
            {
                if(v[i][j]>st[tot])
                {
                    st[++tot]=v[i][j];  
                    v2[i][j]=tot-1;
                }
                else
                {
                    int id=lower_bound(st+1,st+tot+1,v[i][j])-st;   
                    st[id]=v[i][j];
                    v2[i][j]=id-1;
                }
            }
        }
        for(int i=1;i<=n;i++)
        {
            int tot=0;
            st[tot]=-N; 
            for(int j=m;j>=1;j--)
            {
                if(-v[i][j]>st[tot])
                {
                    st[++tot]=-v[i][j];  
                    v4[i][j]=tot-1;
                }
                else
                {
                    int id=lower_bound(st+1,st+tot+1,-v[i][j])-st;   
                    st[id]=-v[i][j];
                    v4[i][j]=id-1;
                }
            }
        }
        for(int i=1;i<=m;i++)
        {
            int tot=0;
            st[tot]=0;
            for(int j=1;j<=n;j++)
            {
                if(v[j][i]>st[tot])
                {
                    st[++tot]=v[j][i];  
                    v5[j][i]=tot-1;
                }
                else
                {
                    int id=lower_bound(st+1,st+tot+1,v[j][i])-st;   
                    st[id]=v[j][i];
                    v5[j][i]=id-1;
                }
            }
        }
        for(int i=1;i<=m;i++)
        {
            int tot=0;
            st[tot]=-N;
            for(int j=1;j<=n;j++)
            {
                if(-v[j][i]>st[tot])
                {
                    st[++tot]=-v[j][i];  
                    v7[j][i]=tot-1;
                }
                else
                {
                    int id=lower_bound(st+1,st+tot+1,-v[j][i])-st;   
                    st[id]=-v[j][i];
                    v7[j][i]=id-1;
                }
            }
        }
        for(int i=1;i<=m;i++)
        {
            int tot=0;
            st[tot]=0;
            for(int j=n;j>=1;j--)
            {
                if(v[j][i]>st[tot])
                {
                    st[++tot]=v[j][i];  
                    v6[j][i]=tot-1;
                }
                else
                {
                    int id=lower_bound(st+1,st+tot+1,v[j][i])-st;   
                    st[id]=v[j][i];
                    v6[j][i]=id-1;
                }
            }
        }
        for(int i=1;i<=m;i++)
        {
            int tot=0;
            st[tot]=-N;
            for(int j=n;j>=1;j--)
            {
                if(-v[j][i]>st[tot])
                {
                    st[++tot]=-v[j][i];  
                    v8[j][i]=tot-1;
                }
                else
                {
                    int id=lower_bound(st+1,st+tot+1,-v[j][i])-st;   
                    st[id]=-v[j][i];
                    v8[j][i]=id-1;
                }
            }
        }
//        cout<<v1[2][4]<<" "<<v2[2][4]<<" "<<v3[2][4]<<" "<<v4[2][4]<<"\n";
//        cout<<v5[2][4]<<" "<<v6[2][4]<<" "<<v7[2][4]<<" "<<v8[2][4]<<"\n";
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            {
//            	cout<<v1[i][j]<<" "<<v2[i][j]<<" "<<v3[i][j]<<" "<<v4[i][j]<<endl;
                int sum=0;
                sum            =max(sum,max(v1[i][j]+v7[i][j],
                                max(v1[i][j]+v8[i][j],
                                max(v2[i][j]+v7[i][j],
                                max(v2[i][j]+v8[i][j],
                                max(v5[i][j]+v3[i][j],
                                max(v5[i][j]+v4[i][j],
                                max(v6[i][j]+v3[i][j],
                                max(v6[i][j]+v4[i][j],
                                max(v1[i][j]+v4[i][j],
                                max(v2[i][j]+v3[i][j],
                                max(v5[i][j]+v8[i][j],
                                v6[i][j]+v7[i][j])
                               )
                               )
                               )
                               )
                               )
                               )
                               )
                               )
                               )
                               )
                               )+1;
                if(sum>ans)
                {
                    ans=sum;
//                    cout<<i<<" "<<j<<endl;
//                    cout<<sum<<endl;
                }
            }
                
        printf("%d\n",ans);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值