牛客 Fake Maxpooling ###K ###K //K

题目链接:https://ac.nowcoder.com/acm/problem/207140

题意:给定n*m的一个矩阵 每个位置上的数为lcm(i,j) 问所有k*k的子矩阵中的最大值的和是多少

思路:暴力求矩阵 时间复杂度 o(n*m*log(n*m))   如果记忆化或者筛法的话 可以o (n*m)    

求出矩阵后  先每一行 单调队列 求出长度k 的最大值, 然后每一列 再用一次单调队列求出 刚刚用行求出的最大值中的 最大值  就可得到结果

不能直接 修改a 数组 必须开一个f 数组来记录 不然a数组可能影响到后面的单调队列 数据水了没判出来

没有优化过的版本

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 #define pb push_back
 5 const int maxn =2e5+10;
 6 const int mod=998244353;
 7 
 8 int a[5005][5005];
 9 int f[5005][5005];
10 
11 int gcd(int a,int b)
12 {
13     if(b==0) return a;
14     return gcd(b,a%b);
15 }
16 int lcm(int a,int b)
17 {
18     return a*b/gcd(a,b);
19 }
20 
21 
22 int main()
23 {
24     ios::sync_with_stdio(false);
25     cin.tie(0);
26     int n,m,k;
27     cin>>n>>m>>k;
28     for(int i=1;i<=n;i++)
29     {
30         for(int j=1;j<=m;j++)
31         {
32             a[i][j]=lcm(i,j);
33         }
34     }
35     for(int i=1;i<=n;i++)
36     {
37         deque<int>q;
38         for(int j=1;j<=m;j++)
39         {
40             while(!q.empty()&&a[i][q.back()]<=a[i][j])
41                 q.pop_back();
42             if(!q.empty()&&q.front()==j-k)
43                 q.pop_front();
44             q.push_back(j);
45             if(j>=k)
46                 f[i][j]=a[i][q.front()];
47         }
48     }
49     ll sum=0;
50     for(int j=k;j<=m;j++)
51     {
52         deque<int>q;
53         for(int i=1;i<=n;i++)
54         {
55             while(!q.empty()&&f[q.back()][j]<=f[i][j])
56                 q.pop_back();
57             if(!q.empty()&&q.front()==i-k)
58                 q.pop_front();
59             q.push_back(i);
60             if(i>=k)
61                 sum+=f[q.front()][j];
62         }
63     }
64     cout<<sum<<'\n';
65 
66 
67 
68 
69 }
View Code

 

能过的记忆化的代码

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 #define pb push_back
 5 const int maxn =5e3+10;
 6 const int mod=1e9+7;
 7 int dp[maxn][maxn];
 8  
 9 int gcd(int a,int b)
10 {
11     if(dp[a][b])
12         return dp[a][b];
13     if(b==0) return dp[a][b]=a;
14     else return dp[a][b]=gcd(b,a%b);
15 }
16 int lcm(int a,int b)
17 {
18     return a*b/gcd(a,b);
19 }
20  
21 int a[maxn][maxn];
22  
23  
24  
25 int main()
26 {
27     ios::sync_with_stdio(false);
28     cin.tie(0);
29     int n,m,k;
30     cin>>n>>m>>k;
31     for(int i=1;i<=n;i++)
32     {
33         for(int j=1;j<=m;j++)
34         {
35             a[i][j]=lcm(i,j);
36         }
37     }
38     ll ans=0;
39     for(int i=1;i<=n;i++)
40     {
41         deque<int>q;
42         for(int j=1;j<=m;j++)
43         {
44             while(!q.empty()&&a[i][q.front()]<=a[i][j])
45                 q.pop_front();
46             if(!q.empty()&&q.back()==j-k)
47                 q.pop_back();
48             q.push_front(j);
49             a[i][j]=a[i][q.back()];
50         }
51     }
52     /*for(int i=1;i<=n;i++)
53     {
54         for(int j=1;j<=m;j++)
55         {
56             cout<<a[i][j]<<" ";
57         }
58         cout<<'\n';
59     }*/
60     for(int i=k;i<=m;i++)
61     {
62         deque<int>q;
63         for(int j=1;j<=n;j++)
64         {
65             while(!q.empty()&&a[q.front()][i]<=a[j][i])
66                 q.pop_front();
67             if(!q.empty()&&q.back()==j-k)
68                 q.pop_back();
69             q.push_front(j);
70             if(j<k)
71                 continue;
72             ans+=a[q.back()][i];;
73         }
74     }
75     cout<<ans<<'\n';
76  
77  
78  
79  
80  
81 }
View Code

 

还有一份能过的 筛法求的矩阵的   时间复杂度o(n*m)

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 #define ull unsigned long long
 5 #define pb push_back
 6 const int maxn=1e6+10;
 7 const int mod=998244353;
 8 int a[5005][5005];
 9 int f[5005][5005];
10  
11 int gcd(int a,int b)
12 {
13     if(b==0) return a;
14     else return gcd(b,a%b);
15 }
16 int lcm(int a,int b)
17 {
18     return a*b/gcd(a,b);
19 }
20  
21  
22 int main()
23 {
24     ios::sync_with_stdio(false);
25     cin.tie(0);
26     int n,m,k;
27     cin>>n>>m>>k;
28     for(int i=1;i<=n;i++)
29     {
30         for(int j=1;j<=m;j++)
31         {
32             if(a[i][j])
33                 continue;
34             for(int k=1;k*i<=n&&k*j<=m;k++)
35             {
36                 a[k*i][k*j]=k;
37             }
38         }
39     }
40     for(int i=1;i<=n;i++)
41     {
42         for(int j=1;j<=m;j++)
43         {
44             a[i][j]=i*j/a[i][j];
45         }
46     }
47     for(int i=1;i<=n;i++)
48     {
49         deque<int>q;
50         for(int j=1;j<=m;j++)
51         {
52             while(!q.empty()&&a[i][q.back()]<=a[i][j])
53                 q.pop_back();
54             if(!q.empty()&&q.front()==(j-k))
55                 q.pop_front();
56             q.push_back(j);
57             if(j>=k)
58                 f[i][j]=a[i][q.front()];
59         }
60     }
61     for(int i=k;i<=m;i++)
62     {
63         deque<int>q;
64         for(int j=1;j<=n;j++)
65         {
66             while(!q.empty()&&f[q.back()][i]<=f[j][i])
67                 q.pop_back();
68             if(!q.empty()&&q.front()==(j-k))
69                 q.pop_front();
70             q.push_back(j);
71             if(j>=k)
72                 f[j][i]=f[q.front()][i];
73         }
74     }
75     ll ans=0;
76     for(int i=k;i<=n;i++)
77     {
78         for(int j=k;j<=m;j++)
79         {
80             ans+=f[i][j];
81         }
82     }
83     cout<<ans<<'\n';
84  
85  
86  
87  
88  
89  
90 }
View Code

 

posted @ 2020-07-15 18:28  canwinfor  阅读(163)  评论(0)    收藏  举报