2020牛客暑期多校训练营(第二场)F题

https://ac.nowcoder.com/acm/contest/5667/F

思路:先把最小公倍数的素组求出来,利用单调队列求出每一行的最大值保存起来,然后再利用一次单调队列依次求出每一列的最大值加起来就是k阶子矩阵的最大值和。
单调队列(滑动窗口求最值):比如有一个素组a,里面有几个数2,6,7,3,1,9.现在有一个长度为3的窗口从i=1的位置往右边移动,求每次移动时候窗口内数的最大值。我们队列里面保存的是入队元素的下标,可以认为队首保存的是当前窗口所在位置最大值的下标,入队时,判断入队元素与队尾元素值的大小,如果队尾元素比入队元素小,那么当前以及在有当前入队元素的位置,队尾元素的值都不可能是最大值,所以删除队尾元素然后入队,如果队尾元素的值比入队元素的值大,那么入队元素在之后窗口的位置还是有可能成为最大值的所以让其入队。

#include <bits/stdc++.h>
#include <iostream>
#include <algorithm>
#include <stdio.h>
const int Max = 100 * 100 * 100 + 5;
#define LL long long
LL mod = 1e9+7;
const int INF = 1e5;
//const int inx = INT_MAX;
using namespace std;
//  srand(time(NULL));
//      m = rand() % 1000 + 1;
//定义i i(A) i+n i+n(B) i+n+n i+n+n(C)
//bitset<Max>s,q;

int gcd(int a,int b)
{
    if(b == 0) return a;
    else return gcd(b,a % b);
}

int lcm(int i,int j)
{
    return i / gcd(i,j) * j;
}

int a[5001][5001];
int b[5001][5001];
deque<int>q;
int main()
{
    int i,j,n,m,k;
    cin >> n >> m >> k;
    for(i = 1; i <= n; i++){
        for(j = 1; j <= m; j++){
            a[i][j] = lcm(i,j);
        }
    }
    for(i = 1; i <= n; i++){
        for(j = 1; j <= m; j++){
            while(!q.empty() && j - k >= q.front()){
                q.pop_front();
            }
            while(!q.empty() && a[i][j] >= a[i][q.back()]){
                q.pop_back();
            }
            q.push_back(j);
            if(j >= k) b[i][j] = a[i][q.front()];
        }
        q.clear();
    }
//    for(i = 1; i <= n; i++){
//        for(j = k; j <= m; j++){
//            cout << a[i][j] << " ";
//        }
//        cout << endl;
//    }
//    for(i = 1; i <= n; i++){
//        for(j = k; j <= m; j++){
//            cout << b[i][j] << " ";
//        }
//        cout << endl;
//    }
    LL sum = 0;
    for(i = k; i <= m; i++){
        for(j = 1; j <= n; j++){
            while(!q.empty() && j - k >= q.front()){
                q.pop_front(); 
            }
            while(!q.empty() && b[j][i] >= b[q.back()][i]){
                q.pop_back();
            }
            q.push_back(j);
            if(j >= k) sum += b[q.front()][i];
        }
        q.clear();
    }
    cout << sum;
    return 0;
}
全部评论

相关推荐

评论
1
收藏
分享

创作者周榜

更多
正在热议
更多
# 面试被问到不会的问题,你怎么应对? #
141次浏览 2人参与
# 参加完秋招的机械人,还参加春招吗? #
119774次浏览 755人参与
# 开放七大实习专项,百度暑期实习值得冲吗 #
17841次浏览 266人参与
# 你觉得大几开始实习最合适? #
134次浏览 2人参与
# 拼多多工作体验 #
52271次浏览 332人参与
# 通信硬件知识分享 #
48071次浏览 537人参与
# 厦门银行科技岗值不值得投 #
9422次浏览 223人参与
# 找AI工作可以去哪些公司? #
15136次浏览 633人参与
# 说说你知道的学历厂 #
390889次浏览 1379人参与
# 从事AI岗需要掌握哪些技术栈? #
13373次浏览 719人参与
# 你做过最难的笔试是哪家公司 #
44658次浏览 636人参与
# 金三银四,你的春招进行到哪个阶段了? #
24138次浏览 295人参与
# 想给25届机械人的秋招建议 #
47667次浏览 251人参与
# AI面会问哪些问题? #
34077次浏览 953人参与
# 中国电信笔试 #
32981次浏览 303人参与
# 我心目中的理想工作是这样的 #
100810次浏览 907人参与
# 携程笔试 #
139510次浏览 839人参与
# 这些公司卡简历很严格 #
94900次浏览 415人参与
# 拼多多集团-PDD笔试 #
37526次浏览 358人参与
# 一人说一个提前实习的好处 #
118425次浏览 711人参与
# 投递几十家公司,到现在0offer,大家都一样吗 #
342687次浏览 2190人参与
# 实习越久越好,还是多多益善? #
91478次浏览 359人参与
牛客网
牛客网在线编程
牛客网题解
牛客企业服务