UCF Local Programming Contest 2019(Practice) F Sub Matrix Sum 【降维+二分单调栈】

Description

You have written many programs to search mazes so matrix search shouldn't be any different, or will it?

Problem

An integer matrix with R rows and C columns has 图片1.png sub matrices. We want to select a sub matrix with sum (the sum of all integers in it) greater than or equal to a given integer S. We want the size of the sub matrix to be the least possible. The size of a sub matrix is defined as the number of elements in that sub matrix (i.e., number of rows * number of columns in that sub matrix). 

Input

The first input line consists of three integers R, C (1 ≤ R ≤ 100,000; 1 ≤ C ≤ 100,000;1 ≤ R*C ≤ 100,000) and S. Next R lines contain the description of the matrix. Each of these R lines contains C integers separated by a single space. All integers (other than R and C) are between -10^9 and +10^9, inclusive. 

Output

Print the size of the minimum sub matrix whose sum is greater or equal to the given S. If there is no such sub matrix, output -1. 

样例输入1

3 3 26
1 2 3
4 5 6
7 8 9 

样例输出1

样例输入2

3 3 0
-1 -2 -3
-4 -5 -6
-7 -8 -9 

样例输出2

-1 

样例输入3

2 2 1
-1 -2
0 2 

样例输出3

 题目大意:

给出一个大小为 R×C 的矩阵,要求选出一个子矩阵,在子矩阵和不小于 S 的条件下,输出子矩阵的最小大小。

分析:

涉及到二维子矩阵的元素和,先降维。枚举起始行 i 和结束行 j ,将 i 到 j 之间的行按列压缩到一维,则对于这个一维数组,问题转化为找到一对 l 和 r ,使得 r-l+1 最小,并且 l 到 r 之间的元素和大于等于 S 。

对一维数组求前缀和,由于这里有负数元素,前缀和会减小,所以用单调栈记录递增的前缀和,对于每个位置 k ,二分单调栈找到第一个小于等于 num[k]-S 的前缀和 num[x] ,则 x 到 k 之间的元素和满足大于等于 S ,并且 x 是满足该条件的最大下标。

具体解释见代码。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <cmath>
#include <vector>
#include <map>
#include <set>
#include <queue>
#define INF 0x3f3f3f3f
#define mst(a,num) memset(a,num,sizeof a)
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define repd(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
typedef pair<ll,ll> PLL;
typedef vector<int> VI;
const ll mod = 1e9 + 7;
const int maxn = 100000 + 5;

vector<vector<ll>> mat;
ll num[maxn];
int r,c;
ll s;
vector<ll> sta;     //单调栈

int solve(){
    int res=INF;
    sta.clear();
    sta.push_back(0);
    rep(i,1,c){
        int l=0,r=sta.size()-1;
        ll tmp=num[i]-s;
        int ans=-1;
        while(l<=r){        //二分查找
            int mid=(l+r)/2;
            if(num[sta[mid]]<=tmp){
                l=mid+1;
                ans=sta[mid];
            }
            else{
                r=mid-1;
            }
        }
        if(ans!=-1){
            res=min(res,i-ans);
        }
        while(!sta.empty()&&num[sta[sta.size()-1]]>=num[i]){        //单调栈操作
            sta.pop_back();
        }
        sta.push_back(i);
    }
    return res;
}

int main() {
    scanf("%d%d%lld",&r,&c,&s);
    //选择r和c中较小的作为行进行存储
    if(r < c){
        mat.resize(r+1);
        rep(i,0,r){
            mat[i].resize(c+1);
        }
        rep(i,1,r){
            rep(j,1,c){
                scanf("%lld",&mat[i][j]);
            }
        }
    }
    else{
        mat.resize(c+1);
        rep(i,0,c){
            mat[i].resize(r+1);
        }
        rep(i,1,r){
            rep(j,1,c){
                scanf("%lld",&mat[j][i]);
            }
        }
        swap(r,c);
    }
    rep(i,1,c){
        mat[0][i]=0;
    }
    //预处理二维前缀和
    rep(i,1,r){
        rep(j,1,c){
            mat[i][j]=mat[i-1][j]+mat[i][j];
        }
    }
    int ans=INF;
    rep(l,1,r){
        rep(rr,l,r){
            num[0]=0;
            rep(i,1,c){
                num[i]=mat[rr][i]-mat[l-1][i];
            }
            rep(i,1,c){
                num[i]+=num[i-1];
            }
            int ret=solve();
            if(ret==INF)  continue;
            ans=min(ans,(rr-l+1)*ret);
        }
    }
    printf("%d\n",ans==INF?-1:ans);
    return 0;
}


 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
UCF101视频动作分类系统是一个用于对视频中的动作进行分类的计算机系统。UCF101是一个广泛应用的视频动作分类数据集,含有101个动作类别,包括“打篮球”、“骑自行车”、“划船”等等。 该系统的主要目的是自动识别视频中的动作类别,这对于视频内容的检索、视频监控、人机交互等领域都具有重要意义。 该系统主要包括以下几个步骤: 1. 数据准备:从UCF101数据集中选择一部分作为训练集和测试集。训练集用于训练分类模型,测试集用于评估模型的性能。同时,还需要对视频进行预处理,如尺寸调整、帧提取等。 2. 特征提取:从视频序列中提取特征表示。常用的方法包括2D/3D卷积神经网络(CNN)、循环神经网络(RNN)等。这些特征可以捕捉到视频中的运动、颜色等信息。 3. 模型训练:使用训练集数据对分类模型进行训练。常用的分类模型包括支持向量机(SVM)、多层感知机(MLP)、卷积神经网络(CNN)等。通过不断调整模型的参数和结构,提高模型的分类性能。 4. 模型评估:使用测试集数据对训练好的模型进行评估。可以使用准确率、召回率、F1值等指标来评估模型的性能。 5. 模型应用:将训练好的模型应用于实际视频动作分类任务中。输入待分类的视频序列,通过模型进行分类,输出视频的动作类别。 UCF101视频动作分类系统是一个复杂而有效的系统,可以帮助我们识别和理解视频中的不同动作,为实际应用提供了有力的支持。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值